이번에는 security의 기본 User클레스를 확장하여 실제로 필요한 회원 정보를 추가하고 security-context.xml에있던 사용자 인증 쿼리를 mybatis로 이동시켜 사용하겠다. 그리고 처음에 포스팅할때 같이 해야 했던 logout도 적용시키겠다.
1.logout은 별거 없다. security-context.xml의 http에
<logout delete-cookies="true" logout-success-url="/user/loginPage" logout-url="/user/logout" invalidate-session="true"/>
를 추가한다.
logout-url : 로그아웃이 요청될 url (이 주소로 요청이 들어오면 security에서 알아서 logout시켜준다)
logout-success-url : 로그아웃이 성공 후 이동할 주소
delete-cookies : 쿠키 삭제 여부
invalidate-session : 세션 제거 여부
2.이제 security에서 제공해주는 User클레스를 확장시켜 사용하는 방법을 알아보자.
우선 security에서 사용중인 User클레스의 내용을 살펴보면 멤버 변수로
//~ Instance fields ==================== private String password; private final String username; private final Set<GrantedAuthority> authorities; private final boolean accountNonExpired; private final boolean accountNonLocked; private final boolean credentialsNonExpired; private final boolean enabled;
가 존재하고 setter가없이 생성자로만 변수값을 지정 할 수 있게 해놨다.
생성자역시 username,password,enabled 만을 입력받는 생성자와
모든 변수를 입력받는 생성자 2개가 존재한다.
값을 가져오는 getter와 계정 잠금여부를 확인하는 is메서드가 존재한다
직접 만들어 확장시킬 클레스는 User클레스를 상속받고 필요한 변수만 추가하여 사용하겠다.
2-1.User클레스를 상속받는 UserDetailsVO 생성(사용법을 익히기 위해 email필드만 추가하겠다.)
(이부분은 UserDetails인터페이스만 상속받아 VO객체를 만들어도 상관이 없지만 User클레스를 이용하여 확장을 할경우 중복세션 방지등의 기능을 추가 적으로 구현하지 않아도 적용시킬수 있어 User클레스를 직접 확장하는 방법을 이용했다.)
package com.min.study.user.vo; import java.util.Collection; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.SpringSecurityCoreVersion; import org.springframework.security.core.userdetails.User; public class UserDetailsVO extends User{ /** * */ private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID; private String email; public UserDetailsVO(String username, String password, boolean enabled, boolean accountNonExpired, boolean credentialsNonExpired, boolean accountNonLocked, Collection<? extends GrantedAuthority> authorities,String email) { super(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, authorities); this.email = email; // TODO Auto-generated constructor stub } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } @Override public String toString() { // TODO Auto-generated method stub return super.toString() + "; Email: "+this.email; } }
3.그리고 mybatis를 이용하여 사용자 정보를 가져올 UserAuthenticationService 생성해야 하는데
일단 security의 인증 절차를 보면 사용자가 입력한 request의 username,password와 디비에서 가져온 정보를 비교하여인증을 하는데 이때 UserDetailsService 인터페이스를 상속받아 loadUserByUsername메서드를 구현하여 필요한 정보를 가져오면 된다.
처음에 UserDetailsService를 상속받아 UserAuthenticationService를 만들었을때는 그냥 간단하게 spring에 등록한 userService를 @Resource를 이용하여 주입시키면 될줄 알았는데 주입이 되지 않았다.
자세한 이유는 모르겠다. 다른 자료를 찾아봐도 JdbcDaoImpl을 이용한 방법뿐이 없었다. 그래서 UserAuthenticationService에 직접 datasource-context.xml에 지정한 mybatis의 sqlSessionTemplate를 받아와 사용하는 방법을 이용했다.
3-1.UserDetailsService를 상속받은 UserAuthenticationService생성
package com.min.study.user.service; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.mybatis.spring.SqlSessionTemplate; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import com.min.study.user.vo.UserDetailsVO; public class UserAuthenticationService implements UserDetailsService { private static final Logger logger = LoggerFactory.getLogger(UserAuthenticationService.class); private SqlSessionTemplate sqlSession; public UserAuthenticationService() { // TODO Auto-generated constructor stub } public UserAuthenticationService(SqlSessionTemplate sqlSession) { // TODO Auto-generated constructor stub this.sqlSession = sqlSession; } @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { // TODO Auto-generated method stub Map<String, Object> user = sqlSession.selectOne("user.selectUser",username); if(user == null ) throw new UsernameNotFoundException(username); logger.info(user.toString()); List<GrantedAuthority> gas = new ArrayList<GrantedAuthority>(); gas.add(new SimpleGrantedAuthority(user.get("authority").toString())); return new UserDetailsVO(user.get("username").toString(), user.get("password").toString(), (Integer)user.get("enabled") == 1, true, true, true, gas,user.get("username").toString()); } }
3-2. security-context.xml에 UserAuthenticationService빈 생성 및 sqlSession주입 및 기존 jdbc-user-service 제거 or 주석 처리
<beans:bean id="userService" class="com.min.study.user.service.UserAuthenticationService"> <beans:constructor-arg name="sqlSession" ref="sqlSession" /> </beans:bean>
3-3. mybatis의 mysql/user.xml에 쿼리 추가
4.사용자 인증 확인
-----------------------------------------------------------------------------------------
소스를 다 작성 하고 포스팅 하는거라 중간에 빠진 내용이 있을지 모르겠다;