기존의 테이블을 이용한 시큐리티 인증 방법
회원 테이블과 권한 테이블
-- 회원 테이블
create table tbl_member(
userid varchar(50) not null primary key,
userpw varchar(100) not null,
username varchar(100) not null,
regdate timestamp default now(),
moddate timestamp default now(),
enabled char(1) default '1'
);
-- 권한 테이블
create table tbl_member_auth(
userid varchar(50) not null,
auth varchar(50) not null,
constraint fk_member_auth foreign key (userid) references tbl_member(userid)
);
BCrypetPasswordEncdoer는 해시 함수로 문자열을 암호화한다. 체크하는 쪽에서는 암호화된 패스워드가 가능한 패스워드인지만 확인하고 다시 원문으로 돌릴 수 없다.
...생략
<security:authentication-manager>
<security:authentication-provider>
<security:jdbc-user-service data-source-ref="dataSource"/>
<security:password-encoder ref="bcryptPasswordEncoder"/>
</security:authentication-provider>
</security:authentication-manager>
#. 4 TEST
@Autowired
private PasswordEncoder pwEncoder;
@Autowired
private DataSource dataSource;
@Test
public void testInsertMember() {
String sql = "INSERT INTO tbl_member(userid, userpw, username)"
+ "values(?,?,?)";
for (int i=0; i < 30; i++) {
try ( Connection conn = dataSource.getConnection();
PreparedStatement pstmt= conn.prepareStatement(sql);
){
//모든 비밀번호는 1234
pstmt.setString(2, pwEncoder.encode("1234"));
if(i < 10) {
pstmt.setString(1, "user"+i);
pstmt.setString(3, "사용자"+i);
} else if(i < 20) {
pstmt.setString(1, "manager"+i);
pstmt.setString(3, "매니저"+i);
} else if(i<30) {
pstmt.setString(1, "admin"+i);
pstmt.setString(3, "관리자"+i);
}
int result = pstmt.executeUpdate();
log.info("result : " + result);
assertTrue(result == 1);
} catch (SQLException e) {
e.printStackTrace();
}
}
}
//권한 부여
@Test
public void testInsertAuth() {
String sql = "INSERT INTO tbl_member_auth(userid, auth)"
+"VALUES(?,?)";
for (int i=0; i < 30; i++) {
try ( Connection conn = dataSource.getConnection();
PreparedStatement pstmt= conn.prepareStatement(sql);
){
if(i < 10) { //유저 권한
pstmt.setString(1, "user"+i);
pstmt.setString(2, "ROLE_USER");
} else if(i < 20) { //매니저 권한
pstmt.setString(1, "manager"+i);
pstmt.setString(2, "ROLE_MANAGER");
} else if(i<30) { //관리자 권한
pstmt.setString(1, "admin"+i);
pstmt.setString(2, "ROLE_ADMIN");
}
int result = pstmt.executeUpdate();
log.info("result : " + result);
assertTrue(result == 1);
} catch (SQLException e) {
e.printStackTrace();
}
}
}
[##Image|kage@bHOBnW/btqIwEalROF/1mIlLaT8JuCj766ycQd8H1/img.png|alignCenter|width="100%" data-origin-width="0" data-origin-height="0" data-ke-mobilestyle="widthContent"|||##]
지정된 방식(JDBC를 이용한 인증)이 아닌, 테이블 구조를 이용하는 경우, 인증 쿼리(users-by-username-query)와 권한을 확인하는 쿼리(authorities-by-username-query)를 이용해서 처리한다.
-- 인증 쿼리
SELECT userid, userpw as password, enabled
FROM tbl_member
WHERE userid='아이디';
-- 권한을 확인하는 쿼리
SELECT userid as username, auth as authority
FROM tbl_member_auth
WHERE userid = '아이디';
위의 쿼리를 PrepareStatement에서 사용하는 구문으로 바꾼다. (WHERE userid=?)
<security:authentication-manager>
<security:authentication-provider>
<security:jdbc-user-service data-source-ref="dataSource"
users-by-username-query=
"SELECT userid, userpw as password, enabled
FROM tbl_member
WHERE userid = ? "
authorities-by-username-query=
"SELECT userid as username, auth as authority
FROM tbl_member_auth
WHERE userid = ? " />
<security:password-encoder ref="bcryptPasswordEncoder"/>
</security:authentication-provider>
</security:authentication-manager>
이제 member테이블에 있는 계정으로 로그인 시,
각 계정이 가진 권한으로 열람할 수 있는 페이지에 접속할 수 있다.