이번편은 security에서 DB의 유저정보를 가져오는 UserDetailsService와

유저정보를가저와 담는 VO정도의 역할로 사용되는 UserDetails를 커스텀 하는법을 배웁니다.


UserDetails

특징

Security에서 사용자의 정보를 담는 인터페이스가 UserDetails 인터페이스이다.

이 인터페이스를 구현하게 되면 이제 Security 인증, 인가 관련 작업에서 우리가 구현한 인터페이스를 기준으로 작업하게 될 것이다.

CustomUserDetails.java

기본적인 오버라이딩 메소드들은 오버라이딩하고,
다른 추가적인 회원 정보 컬럼이 있다면 멤버변수로 추가하고 getter, setter을 추가해주면 된다.
VO라고 보면됨.

package com.lec.security;

import java.util.ArrayList;
import java.util.Collection;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

public class CustomUserDetails implements UserDetails {

    private String ID;
    private String PASSWORD;
    private String NAME;
    private String AUTHORITY;
    private boolean ENABLED;

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        ArrayList<GrantedAuthority> auth = new ArrayList<GrantedAuthority>();
        auth.add(new SimpleGrantedAuthority(AUTHORITY));
        return auth;
    }

    @Override
    public String getPassword() {
        return PASSWORD;
    }

    @Override
    public String getUsername() {
        return ID;
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return ENABLED;
    }

    public String getNAME() {
        return NAME;
    }

    public void setNAME(String name) {
        NAME = name;
    }

}


UserDetailsService

특징

DB에서 유저 정보를 가져오는 역할을 한다.

UserDetailsService 인터페이스에서 DB에서 유저정보를 불러오는 중요한 메소드는 loadUserByUsername() 메소드이다.

loadUserByUsername()메소드에서 CustomUserDetails형으로 사용자의 정보를 받아오면 된다.

CustomUserDetailsService.java

package com.lec.security;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;

public class CustomUserDetailsService implements UserDetailsService {

    @Autowired
    private UserAuthDAO userAuthDAO;


   @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        CustomUserDetails user = userAuthDAO.getUserById(username);
        if(user==null) {
            throw new UsernameNotFoundException(username);
        }
        return user;
    }
}

DAO, SQL

UserAuthDAO.java

package com.lec.security;

import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

@Repository("userAuthDAO")
public class UserAuthDAO {

    @Autowired
    private SqlSessionTemplate sqlSession;

    public CustomUserDetails getUserById(String username) {
        return sqlSession.selectOne("user.selectUserById", username);
    }

}

user_sql.xml

src/main/resources/mapper/user_sql.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="user">

     <select id="selectUserById" resultType="com.lec.security.CustomUserDetails">
        <![CDATA[
            SELECT
                *
            FROM
                user
            WHERE
                ID=#{ loginId}
        ]]>
    </select>

 </mapper>

security-context.xml

커스터마이징 했으므로 기존의 jdbc-user-service는 지워도 된다.

<?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:context="http://www.springframework.org/schema/context"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://www.springframework.org/schema/beans
                                 http://www.springframework.org/schema/beans/spring-beans.xsd
                                 http://www.springframework.org/schema/security
                                 http://www.springframework.org/schema/security/spring-security.xsd
                                 http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd
                                 http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">


        <context:component-scan base-package="com.lec.security"/>


        <http auto-config="true" use-expressions="false">
            <intercept-url pattern="/**" access="ROLE_USER" />
        </http>


        <authentication-manager>
            <authentication-provider user-service-ref="userService"></authentication-provider>
        </authentication-manager>

        <beans:bean id="userService" class="com.lec.security.CustomUserDetailsService"/>

</beans:beans>