07. spring security 사용자 정보 확장 & mybatis를 이용한 인증 처리& 로그아웃처리
-
이번에는
security
의 기본 User클레스를 확장하여 실제로 필요한 회원 정보를 추가하고security-context.xml
에있던 사용자 인증 쿼리를mybatis
로 이동시켜 사용하겠다. 그리고 처음에 포스팅할때 같이 해야 했던logout
도 적용시키겠다. -
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
: 세션 제거 여부
이제 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클레스를 상속받고 필요한 변수만 추가하여 사용하겠다.
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;
}
}
mybatis
를 이용하여 사용자 정보를 가져올UserAuthenticationService
생성security
의 인증 절차를 보면 사용자가 입력한 request의username
,password
와 디비에서 가져온 정보를 비교하여인증UserDetailsService
인터페이스를 상속받아loadUserByUsername
메서드를 구현하여 필요한 정보를 가져오면 된다.
처음에 UserDetailsService
를 상속받아 UserAuthenticationService
를 만들었을때는 그냥 간단하게 spring에 등록한 userService
를 @Resource
를 이용하여 주입시키면 될줄 알았는데 주입이 되지 않았다.
자세한 이유는 모르겠다. 다른 자료를 찾아봐도 JdbcDaoImpl을 이용한 방법뿐이 없었다. 그래서 UserAuthenticationService
에 직접 datasource-context.xml
에 지정한 mybatis
의 sqlSessionTemplate
를 받아와 사용하는 방법을 이용했다.
나중에 알고보니
UserAuthenticationService
서비스를 스프링에서 인식할수 있게 어노테이션이나 xml에 빈을 추가하면 됨.
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());
}
}
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>
mybatis
의mysql/user.xml
에 쿼리 추가
<select id="selectUser" resulttype="map">
SELECT
EMAIL as username,
PASSWD as password,
ENABLED as enabled,
AUTHORITY as authority
FROM USER
WHERE EMAIL = #{username}
</select>
- 사용자 인증 확인
소스를 다 작성 하고 포스팅 하는거라 중간에 빠진 내용이 있을지 모르겠다;
Comments