1. emp 테이블을 스프링 시큐리티에서 커스텀마이징 하시오.
1-1. 소스코드 (VO 객체)
@AllArgsConstructor
@NoArgsConstructor
@Setter
@Getter
@ToString
public class EmpVO {
/* private int empno; */
private String empno; // NOT NULL NUMBER(4)
private String ename; // VARCHAR2(10)
private String job; // VARCHAR2(9)
private int mgr; // NUMBER(4)
private Timestamp hiredate; // DATE
private int sal; // NUMBER(7,2)
private int comm; // NUMBER(7,2)
private int deptno; // NUMBER(2)
private String authority;
private List<AuthVO> authList;
}
1-2. 소스코드 (User 객체)
@Setter
@Getter
@ToString
// 스프링 시큐리티의 User 객체 상속
public class EmpUser extends User {
private EmpVO emp;
public EmpUser(String ename, String empno, Collection<? extends GrantedAuthority> authorities) {
super(ename, empno, authorities);
}
public EmpUser(EmpVO empVO) {
super(empVO.getEname(), empVO.getEmpno(), getAuth(empVO));
this.emp = empVO;
}
// 유저가 갖고 있는 권한 목록
public static Collection<? extends GrantedAuthority> getAuth(EmpVO empVO) {
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
for (AuthVO auth : empVO.getAuthList()) {
authorities.add(new SimpleGrantedAuthority(auth.getAuthority()));
}
return authorities;
}
}
1-3. 소스코드 ( DetailsService 객체)
@Log4j
@Service
// 스프링 시큐리티의 UserDetailsService의 인터페이스 구현
public class EmpDetailsService implements UserDetailsService {
@Setter(onMethod_ = @Autowired)
private EmpMapper empMapper;
@Override
public UserDetails loadUserByUsername(String ename) throws UsernameNotFoundException {
log.warn("Load User By EmpVO number: " + ename);
EmpVO vo = empMapper.getEmp(ename);
log.warn("Query by EmpVO mapper: " + vo);
return vo == null ? null : new EmpUser(vo);
}
}
1-4. 소스코드 ( Mapper 객체)
@Mapper
public interface EmpMapper {
EmpVO getEmp(String ename);
}
1-5. Mapper XML파일
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="edu.bit.ex.mapper.EmpMapper">
<resultMap id="empMap" type="edu.bit.ex.vo.EmpVO">
<result property="ename" column="ename"/>
<result property="empno" column="empno"/>
<result property="hiredate" column="hiredate"/>
<result property="mgr" column="mgr"/>
<result property="sal" column="sal"/>
<result property="comm" column="comm"/>
<result property="deptno" column="deptno"/>
<result property="authority" column="authority"/>
<collection property="authList" resultMap="authMap"></collection>
</resultMap>
<resultMap id="authMap" type="edu.bit.ex.vo.AuthVO">
<result property="username" column="ename"/>
<result property="authority" column="authority"/>
</resultMap>
<select id="getEmp" resultMap="empMap">
SELECT empno, ename, mgr, hiredate, sal, comm, deptno,
CASE WHEN job = 'MANAGER'
THEN 'ROLE_ADMIN'
ELSE 'ROLE_USER'
END authority
FROM emp01
WHERE ename = #{ename}
</select>
</mapper>
1-6. Context XML 파일
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 해당 프로토콜의 로그인 감지 -->
<http auto-config="true" use-expressions="true">
<!-- 권한을 부여하여 해당 조건을 만족하지 않을때 로그인 페이지로 인터셉트한다 -->
<intercept-url pattern="/login/loginForm" access="permitAll" />
<intercept-url pattern="/" access="permitAll" />
<intercept-url pattern="/admin/**" access="hasRole('ADMIN')" />
<intercept-url pattern="/user/**" access="permitAll" />
<intercept-url pattern="/**" access="hasAnyRole('USER, ADMIN')" />
<!-- 로그인 폼 구현 -->
<!-- form-login 태그로 기초적인 형태가 구축되고 속성값에 의해 커스터마이징 할 수 있다 -->
<form-login login-page="/login/loginForm"
default-target-url="/"
authentication-failure-url="/login/loginForm?error"
username-parameter="id"
password-parameter="password" />
<!-- 로그아웃 폼 구현 -->
<logout logout-url="/logout" logout-success-url="/" />
<!-- 403(접근 거부) 에러 처리 -->
<!-- 인증값과 권한값이 매칭이 안될경우 발생시킨다 -->
<access-denied-handler error-page="/login/accessDenied"/>
</http>
<!-- 암호화 인코딩 객체 설정 -->
<beans:bean id="customNoOpPasswordEncoder" class="edu.bit.ex.security.CustomNoOpPasswordEncoder"/>/>
<!-- DetailsService 설정 -->
<beans:bean id="empDetailsService" class="edu.bit.ex.security.EmpDetailsService" />
<!-- provider -->
<!-- DB에서 설정한 쿼리문으로 필요한 데이터들을 불러온다 -->
<authentication-manager>
<authentication-provider user-service-ref="empDetailsService">
<!-- 패스워드 인코딩을 설정한다 -->
<password-encoder ref="customNoOpPasswordEncoder"/>
</authentication-provider>
</authentication-manager>
</beans:beans>
1-7. 소스코드 (UserService 객체)
@Log4j
@NoArgsConstructor
@Service
public class UserService {
@Inject
private CustomNoOpPasswordEncoder passEncoder;
@Inject
private UserMapper userMapper;
@Transactional(rollbackFor = Exception.class)
public void addUser(UserVO userVO) {
String password = userVO.getPassword();
String encode = passEncoder.encode(password);
userVO.setPassword(encode);
userMapper.insertUser(userVO);
userMapper.insertAuthorities(userVO);
}
}
'WebDev > 본과정' 카테고리의 다른 글
Log4j와 스프링 부트 기초 (0) | 2021.05.17 |
---|---|
스프링 시큐리티의 세션, 공격기법 대처 및 소셜 로그인 (0) | 2021.05.17 |
카카오톡 소셜로그인 (0) | 2021.05.17 |
Spring Security (0) | 2021.05.17 |
목표 지향 프로그래밍 (0) | 2021.05.17 |
최근댓글