DOing
[Spring Security] DB를 이용하여 로그인 본문
이전 포스팅에서는 특정한 계정에 대해서 로그인 처리를 하였다. 이번 포스팅에서는 좀 더 현실적으로 DB를 이용하는 방식을 이용해보자.
1. root-context.xml 확인
dataSource라는 빈이 제대로 지정되어 있는 확인한다.
<bean id ="dataSource" class = "com.zaxxer.hikari.HikariDataSource" destroy-method="close">
<constructor-arg ref ="hikariConfig"/>
</bean>
<bean id = "hikariConfig" class = "com.zaxxer.hikari.HikariConfig">
<property name ="driverClassName" value="net.sf.log4jdbc.sql.jdbcapi.DriverSpy"></property>
<property name ="jdbcUrl" value = "jdbc:log4jdbc:oracle:thin:@localhost:1521:xe"></property>
<property name="username" value="BOOK"></property>
<property name="password" value="BOOK"></property>
</bean>
2. 테이블 생성
3. security-context.xml 수정
<security:authentication-manager>
<security:authentication-provider>
<security:jdbc-user-service data-source-ref="dataSource"/>
</security:authentication-provider>
</security:authentication-manager>
4. PasswordEncoder
스프링 시큐리티 5부터는 PasswordEncoder를 지정해야한다. 이전 포스팅에서는 임시로 {noop}을 사용해서 진행했지만 데이터 베이스를 이용하는 경우에는 PasswordEncoder를 사용해야 한다.
PasswordEncoder는 패스워드를 암호화 시킨다. 암호화되지 않은 실제 패스워드를 저장하거나 사용하는 일은 위험하다. 때문에 암호화된 패스워드로 저장하고, 사용자가 패스워드를 입력하면 이를 암호화해서 저장된 암호화된 비밀번호와 비교한다.
PasswordEncoder는 인터페이스로 설계되어 있고 여러 종류의 구현 클래스가 존재한다. 그 중에서 BCyptPasswordEncoder를 사용해서 패스워드를 암호화해서 처리하자. BCyptPasswordEncoder는 패스워드를 저장하는 용도로 설계되었다. 해시 함수로 특정 문자열을 암호화하기 때문에 암호화를 한 후에, 다시 원문으로 돌리지 못한다.
<bean id ="bcryptPasswordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>
<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>
5. 암호화된 패스워드를 가지는 유저 추가
데이터베이스에도 BCyptPasswordEncoder로 암호화된 패스워드가 저장되어야한다. 아직 회원가입 기능을 구현하지 않은 상태이기 때문에 테스트 코드를 사용해서 유저를 추가한다.
[ Membertest.java ]
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({
"file:src/main/webapp/WEB-INF/spring/root-context.xml",
"file:src/main/webapp/WEB-INF/spring/security-context.xml"})
public class MemberTests {
@Setter(onMethod_ = @Autowired)
private PasswordEncoder pwencoder;
@Setter(onMethod_ = @Autowired)
private DataSource ds;
// 유저 추가
@Test
public void testInsertMember() {
String sql = "insert into tbl_member(userid, userpw, username) values (?,?,?)";
for(int i = 0; i < 10; i++) {
Connection con = null;
PreparedStatement pstmt = null;
try {
con = ds.getConnection();
pstmt = con.prepareStatement(sql);
pstmt.setString(2, pwencoder.encode("pw" + i));
if(i <8) {
pstmt.setString(1, "user"+i);
pstmt.setString(3,"사용자"+i);
}else if (i <9) {
pstmt.setString(1, "manager"+i);
pstmt.setString(3,"매니저"+i);
}else {
pstmt.setString(1, "admin"+i);
pstmt.setString(3,"관리자"+i);
}
pstmt.executeUpdate();
}catch(Exception e) {
e.printStackTrace();
}finally {
if(pstmt != null) { try { pstmt.close(); } catch(Exception e) {} }
if(con != null) { try { con.close(); } catch(Exception e) {} }
}
}
}
// 권한 추가
@Test
public void testInsertAuth() {
String sql = "insert into tbl_member_auth (userid, auth) values (?,?)";
for(int i = 0; i < 10; i++) {
Connection con = null;
PreparedStatement pstmt = null;
try {
con = ds.getConnection();
pstmt = con.prepareStatement(sql);
if(i <8) {
pstmt.setString(1, "user"+i);
pstmt.setString(2,"ROLE_USER");
}else if (i <9) {
pstmt.setString(1, "manager"+i);
pstmt.setString(2,"ROLE_MEMBER");
}else {
pstmt.setString(1, "admin"+i);
pstmt.setString(2,"ROLE_ADMIN");
}
pstmt.executeUpdate();
}catch(Exception e) {
e.printStackTrace();
}finally {
if(pstmt != null) { try { pstmt.close(); } catch(Exception e) {} }
if(con != null) { try { con.close(); } catch(Exception e) {} }
}
}//end for
}
}
6. 쿼리를 사용하는 인증
spring security에서 기본 제공하는 유저와 권한 테이블이 아닌 직접 테이블을 만들어서 사용하는 경우에는 인증을 위한 쿼리와 권한을 확인하는 쿼리가 필요하다. 인증을 위한 쿼리는 users-by-username-query로, 권한을 확인하는 쿼리는 authorities-by-username-query로 지정한다.
<bean id ="bcryptPasswordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>
<security:authentication-manager>
<security:authentication-provider>
<security:jdbc-user-service data-source-ref="dataSource"/>
<security:jdbc-user-service data-source-ref="dataSource"
users-by-username-query="select userid, userpw, enabled from tbl_member where userid=?"
authorities-by-username-query="select userid, auth from tbl_member_auth where userid=?"/>
<security:password-encoder ref="bcryptPasswordEncoder"/>
</security:authentication-provider>
</security:authentication-manager>
'Spring' 카테고리의 다른 글
[Maven] Maven에 대해 알고 사용해보자 (0) | 2021.05.08 |
---|---|
[Spring Security] UserDetailsService를 이용한 인증 (0) | 2021.04.28 |
[Spring Security] 소셜로그인 - 네이버 (0) | 2021.04.11 |
[Spring Boot] 세션저장소 (0) | 2021.04.11 |
[Spring Security] 소셜 로그인 - 구글 (0) | 2021.04.10 |