MySql Password Encoder

Posted at 2013. 9. 21. 19:24 | Posted in Framework/Spring Security
개인적으로 자주 사용하는 Spring Security Password Encoder 입니다.

MySql 의 password() 펑션 알고리즘 사용합니다.

import java.security.GeneralSecurityException; import java.security.MessageDigest; import org.springframework.security.crypto.password.PasswordEncoder; public class MySqlPasswordEncoder implements PasswordEncoder { @Override public String encode(CharSequence rawPassword) { if (rawPassword == null) { throw new NullPointerException(); } byte[] bpara = new byte[rawPassword.length()]; byte[] rethash; int i; for (i = 0; i < rawPassword.length(); i++) bpara[i] = (byte) (rawPassword.charAt(i) & 0xff); try { MessageDigest sha1er = MessageDigest.getInstance("SHA1"); rethash = sha1er.digest(bpara); // stage1 rethash = sha1er.digest(rethash); // stage2 } catch (GeneralSecurityException e) { throw new RuntimeException(e); } StringBuffer r = new StringBuffer(41); r.append("*"); for (i = 0; i < rethash.length; i++) { String x = Integer.toHexString(rethash[i] & 0xff).toUpperCase(); if (x.length() < 2) r.append("0"); r.append(x); } return r.toString(); } @Override public boolean matches(CharSequence rawPassword, String encodedPassword) { if (encodedPassword == null || rawPassword == null) { return false; } if (!encodedPassword.equals(encode(rawPassword))) { return false; } return true; } }


적용 예시..

	<security:authentication-manager alias="authenticationManager">
		<security:authentication-provider user-service-ref="userService">
			<security:password-encoder ref="passwordEncoder" />
		</security:authentication-provider>
	</security:authentication-manager>

	<bean id="passwordEncoder" class="MySqlPasswordEncoder">


'Framework > Spring Security' 카테고리의 다른 글

AJAX Login with Spring Security  (7) 2013.12.12
Spring Security Session Destroy  (3) 2013.10.27
MySql Password Encoder  (0) 2013.09.21

댓글 (Comment)

Name*

Password*

Link (Your Website)

Comment

SECRET | 비밀글로 남기기

Infinite Routing DataSource

Posted at 2013. 1. 13. 18:54 | Posted in Java+/Example

스프링을 이용하여 몇개의 데이터소스를 정해놓고 라우팅을 하는 경우 AbstractRoutingDataSource를 이용할 수 있었습니다.


하지만 경우에 따라 접속해야하는 데이터베이스가 무한대일 경우?



그래서 이것저것 생각해 봤는데 -_-.... 


로그인시에 [고객 코드], [아이디], [비밀번호] 3가지를 입력 받습니다.


[고객코드]로 고객을 찾은 후 고객의 정보로 디비 정보를 만든 후 ThreadLocal에 저장합니다.


그 후 로그인 처리를 합니다.


로그인 시에 데이터소스를 사용할 때 ThreadLocal에 있는 디비 정보(DbInfo 객체)로 데이터소스를 만들거나 캐쉬에서 가져오게 합니다.


로그인 때에 처음 그 데이터베이스에 접속을 하게 되니까 RoutingDataSource 부분에서 데이터소스를 처음 만들게 될 것입니다.



로그인 처리 이후에는 인터셉터를 이용하여 세션에 있는 디비 정보를 ThreadLocal에 넣고 사용하면 되겠습니다.



이렇게 하면 똑같은 쿼리를 사용하면서 [코객코드]에 따라 다른 디비에 붙어서 사용할 수 있겠네요 ㅠ_ㅠ




Spring + Spring Security + Mybatis + SQLite 를 이용해서 샘플을 만들어 봤습니다.


아래와 같이 3개의 고객 스키마가 있습니다.



아래 테이블은 manager 스키마의 고객 관리 테이블 입니다.



비밀번호는 SALT 와의 조합으로 ARIA 알고리즘으로 저장됩니다.


SQLite는 파일 디비라서 직접적으로 아이디와 비밀번호는 사용하지 않습니다.




아래 테이블은 각각 고개 스키마에 있는 사용자 관리 테이블입니다. 암호는 MySQL 의 password() 알고리즘으로 저장됩니다.



계정은 각각 아래와 같이 들어 있습니다. 스키마명은 고객코드와 동일하게 했습니다.


cust001 (비밀번호: 12345 , welcome1!)



cust002 (비밀번호: jsnot)



cust003 (비밀번호: 11111)





핵심 소스 부분 몇 개 살펴보면...


package com.tistory.antop.service.common.impl;


public class LoginSoImpl implements LoginSo {


private AccountMapper accountMapper;


@Override

public Authentication login(String accountId, String username,

String password) {

// 고객 정보 조회

Account account = accountMapper.selectById(accountId);


// 없거나 사용 중지인 경우 예외

if (account == null || account.isUse() == false) {

throw new AccountNotFoundException();

}


// 디비 정보를 만듬

DbInfo dbInfo = new DbInfo();

dbInfo.setUsername(account.getId());

dbInfo.setEncPass(account.getEncPass());

dbInfo.setSalt(account.getSalt());


// ThreadLocal 에 저장

DbInfoContextHolder.set(dbInfo);


// Spring Security 인증

UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(

username, password);

token.setDetails(account);


Authentication auth = authenticationManager.authenticate(token);


return auth;

}

}



아래 소스는 o.s.jdbc.datasource.lookup.AbstraceRoutingDataSource 클래스를 상속받아 구현한 RoutingDataSource 입니다.


캐쉬 역할을 하는 객체는 동기화를 위해 Hashtable을 사용하였습니다.


package com.tistory.antop.framework.datasource;


abstract public class RoutingDataSource extends AbstractRoutingDataSource {


private String url;

private String driverClassName;

private PasswordDecoder passwordDecoder;


private Map<DbInfo, DataSource> dataSources = new Hashtable<DbInfo, DataSource>();


@Override

protected DbInfo determineCurrentLookupKey() {

return DbInfoContextHolder.get();

}


@Override

protected DataSource determineTargetDataSource() {


DbInfo dbInfo = determineCurrentLookupKey();


if (dbInfo == null) {

throw new RoutingDataSourceException("데이터베이스 정보가 없습니다.");

}


try {

// 데이터소스가 없으면 생성

if (!contains(dbInfo)) {

// 비밀번호 복호화

String password = passwordDecoder.decodePassword(

dbInfo.getEncPass(), dbInfo.getSalt());

DataSource ds = createDataSource(dbInfo.getUsername(), password);

add(dbInfo, ds);

}


// 데이터소스 리턴

return get(dbInfo);

} catch (Exception e) {

throw new RoutingDataSourceException(e);

}


}


// 데이터 소스를 만드는 부분은 상속받은 객체가 함

abstract public DataSource createDataSource(String username, String password);

)




WAR 파일


바로 배치 가능한 WAR 파일입니다.


routing_datasource.zip.001


routing_datasource.zip.002



소스 ZIP 파일


이클립스 메이븐 구조의 프로젝트 소스입니다.


routing_datasource.zip



개발 테스트 : 톰켓 7, 웹로직 12c


배포 테스트 : 웹로직 12c




※ 질문!!!


웹로직에서 사용할 때 컨텍스트루트 다음에 "/" 가 붙느냐 안붙느냐에 따라서 스프링 시큐리티 필터를 타고 안타고 다른 결과가 나옵니다...


 URL  정상 처리 여부

 http://localhost:7001/routing_datasource/

 정상 처리 됨
 http://localhost:7001/routing_datasource

 스프링 시큐리티 필터를 타지 못하고 그냥 넘어가서 에러


톰켓에서는 "/" 상관없이 정상적으로 됨.... 이 부분 해결법 아시는분.. ㅠㅠ



'Java+ > Example' 카테고리의 다른 글

LOGBack Configurator with JMX  (0) 2014.07.20
현지어로 언어명 보여주기  (0) 2014.02.09
2014년 도로명 주소 사용에 따른 우편번호 준비  (2) 2013.12.22
JSTL Custom Tag using Spring Beans  (0) 2013.12.01
Spring Message Source from Database  (1) 2013.03.03
Infinite Routing DataSource  (1) 2013.01.13
Mybatis Type Handler  (1) 2012.09.30
Using AUTO_INCREMENT keys  (0) 2011.03.01
  1. hsji
    아주 큰 도움이 되었습니다.

댓글 (Comment)

Name*

Password*

Link (Your Website)

Comment

SECRET | 비밀글로 남기기

Proftpd Manager

Posted at 2012. 12. 10. 05:11 | Posted in Mini Project

드디어 오랜기간의 방황을 깨고 마무리가 되었습니다. ㅠ_ㅠ


빠진 기능도 있고 버그도 있겠지만(?) 다음 과제(?)를 위해서 마무리~




소개...

 

Ubuntu 에 Proftpd 와 Mysql 을 이용해서 사용자 관리와 파일 전송 기록을 남길 수가 있습니다.

 

http://www.sysadminworld.com/2011/install-proftpd-with-mysql-backend-on-debian-ubuntu/

 

 

위와 같은 테이블로 관리를 하게 됩니다.

 

유저와 그룹을 관리하고 쌓이기만 하는 전송 기록을 볼 수 있는 웹어플을 한번 만들어 봤습니다.

 

※ 원래 데이터베이스는 MySQL 인데 샘플을 위해서 SQLite 로 데이터를 옮겼습니다.

 

 


 

사용한 기능...

 

Spring Framework 3

  - Core, AOP, MVC

 

Spring Security 3

  - AuthenticationManager 를 이용한 인증 처리

  - @PreAuthorize 어노테이션을 사용한 서비스단 메소드 보안

  - MySQL 의 password() 로직을 사용한 PasswordEncoder

 

MyBatis 3

  - List<String> ↔ 콤마 구분 문자열 타입 핸들러

  - Date ↔ datetime 타입 핸들러

 

Ext JS 4

  - 컴포넌트 동적 로딩 (필요한 클래스 js 파일을 그때그때 AJAX 로 로드)

  - 페이징 가능한 Tree Grid

  - 플러그인

    - FilterBar, MultiSorting, PagingToolbarResizer 등... -_-;




화면 설명... 


최초 페이지 로딩 후 전송 이력(History)에서 시작합니다. 데이터를 불러오려다가 로그인이 안되어 있어서 인증창이 뜹니다.



로그인이 성공하게 되면 데이터를 불러옵니다.


파일명과 접속 아이피는 문제가 될 소지가 있어서 이상하게 변환시켜 놨습니다 -_-;;;


 

아래는 사용자 관리 화면입니다. 사용자를 추가/수정/삭제 할수 있습니다.



사용자의 권한이 "관리자"만 그룹/사용자 정보를 관리할 수 있습니다. 그냥 "사용자"는 변경하려고 하면 권한이 없다고 나옵니다.



아래는 그룹 관리 화면입니다. 그룹을 추가/수정/삭제 하고, 사용자를 그룹에 포함/제외 시킬 수 있습니다.





소스 다운로드...


proftpd-maven.zip


위 파일은 이클립스 프로젝트 파일입니다. 메이븐 구조로 되어있습니다.


proftpd.war.zip.001


proftpd.war.zip.002



위 2개 파일은 war 파일을 7-zip으로 분할 압축 해놓은 겁니다.


압축 해제 후 나온 war 파일을 바로 배치 후 볼 수 있습니다. (소스 파일들도 들어있슴)

'Mini Project' 카테고리의 다른 글

Image Pyramid  (0) 2014.01.30
Proftpd Manager  (0) 2012.12.10
게시판 2.0  (5) 2011.07.27
Sudoku  (0) 2011.06.09
간단한 JAVA 실행기(?)  (1) 2011.03.21
Forecast Repository  (8) 2010.11.30
Sales History API  (2) 2010.05.27
Order Entry API  (0) 2010.05.13
Human Resources API  (0) 2010.05.10
게시판 1.0  (1) 2010.03.11
비밀번호 생성기(Generate Password)  (1) 2010.02.10

댓글 (Comment)

Name*

Password*

Link (Your Website)

Comment

SECRET | 비밀글로 남기기