티스토리 뷰

remember-me.. 나를 기억해 라는 영화가 문득 떠올랐다. 뭔 내용인지는 거의 90프로 까먹는것 같다. 머리가 점점 휘발성이 되어가는것 같다. 무튼.. 우리가 일상에서 많이 사용하는 자동로그인, 로그인유지 등등의 표현으로 많이 사용하고 있는 remember-me 라는 Spring Security의 기능에 대해 살펴보도록 하겠다. 

remember-me가 무슨 기능이냐? 로그인시에 위와 같이 '로그인 유지'라고 되어 있는 체크박스에 체크를 하고 로그인을 하면 내가 브라우저를 닫거나 개발자도구에서 세션을 끊어버리는 등 직접 로그아웃 버튼을 눌러 로그아웃을 하지 않는 이상 remember-me라는 기능이 계속 로그인을 유지시켜준다. 

잘 하시는 분들은 이런 기능들을 설명할때도 시퀀스 다이어그램이나 클래스 다이어그램 등을 그리며 멋지게 설명을 해주시지만 나는 잘 못하기에 내가 만들어본 기능을 예제로 보여주며 설명을 하도록 하겠다. 

remember-me는 크게 db에 보관하는 방식과 token에 보관하는 방식이 있는데 필자는 token에 보관하는 방식이다. 


Login Page (html)

일단은 저 체크박스를 만들어야 한다. 

<p>
  <label for="remember-me" style>로그인 유지</label>
  <input type="checkbox" id="remember-me" name="remember-me" />
</p>

로그인 하는 부분에 살포시 이 체크박스를 껴 넣어주자. 다른건 맘대로 해도 checkbox의 name은 remember-me로 하도록 하자. (바꿀수도 있지만 굳이.. 그냥 기본값을 사용하자.)

 

Security Config

Spring Security 설정에는 다음 부분을 추가해주도록 하자. 

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private RemembermeUserDetailsService remembermeUserDetailsService;
    
    ... 생략 ...
    
    @Override
    public void configure(HttpSecurity http) throws Exception {
    
    ... 생략 ...
    http.rememberMe()
        .key("oingdaddy!")
        .rememberMeParameter("remember-me")
        .tokenValiditySeconds(86400 * 30)
        .userDetailsService(remembermeUserDetailsService)
        .authenticationSuccessHandler(loginSuccessHandler());
        
    }
    
    @Bean 
    public LoginSuccessHandler loginSuccessHandler() {
        LoginSuccessHandler handler = new LoginSuccessHandler();
        handler.setDefaultTargetUrl("/main");
        return handler;
    }

Security의 설정을 하는 부분 중 configure 메소드를 수정한다. http.rememberMe 라는 메소드가 있고 이곳에서 remember-me에 대한 설정을 할 수 있다.

  • key : 인증받은 사용자의 정보로 token을 생성하는데 사용되는그때 사용되는 값이다. 필수이다. 
  • rememberMeParameter : html에서 checkbox name에 해당하는 값이다. 쓰지 않으면 remember-me가 적용된다. 
  • tokenValiditySeconds : remember-me token의 유효 시간이다. 필자는 한달을 설정해 놓은것이다. 
  • userDetailService : 인증하는데 필요한 UserDetailService를 넣어줘야 한다. 없다면 만들어야 한다. 필수다!
  • authenticationSuccessHandler : remember-me로 로그인 성공 했을때 액션에 대해서 정의해줄수 있는 handler이다. 

이렇게 설정을 해주면 설정은 모두 끝난다. Spring Security로 로그인을 여러가지 방식으로 구현할 수 있는데 필자는 UserDetailService를 사용하지 않는 방식이었다. 그래서 이번에 UserDetailService도 하나 만들었다. 왜냐면 없으면 remember-me 기능을 사용할 수 없다. 

 

RemembermeUserDetailService.java

@Service
public class RemembermeUserDetailsService implements UserDetailsService {

    @Autowired
    private AuthService authService;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
                       
        Map<String, Object> user = authService.getUser(username);

        if (user == null) {
            throw new UsernameNotFoundException(username + "is not found.");
        }
        
        CustomUserDetails customUserDetails = new CustomUserDetails(username, user.get("USER_PWD").toString());
        customUserDetails.setRoles((List<GrantedAuthority>) getAuthorities(username));
        
        return customUserDetails;
    }

    public Collection<GrantedAuthority> getAuthorities(String username) {
                
        List<Object> authList = authService.getUserRolesList(username);
        List<GrantedAuthority> roles = new ArrayList<GrantedAuthority>();
        
        for(int inx = 0 ; inx < authList.size() ; inx ++) {
            Map<String, String> auth = (Map<String, String>) authList.get(inx);
            roles.add(new SimpleGrantedAuthority(auth.get("AUTHORITY")));
        }
        
        return roles;
    }

}

username 가지고 CustomUserDetails를 만들어주는 것이라고 보면 된다. 권한 정보까지 모두 가지고 있어야 remember-me로 로그인을 한다고 해도 온전하게 권한에 따라 컨트롤이 가능하다. 

 

CustomUserDetail은 무엇이냐?

public class CustomUserDetails implements UserDetails {
     
    private String username;
    private String password;
    private List<Map<String,String>> authenticatedMenu = new ArrayList<Map<String,String>>();
    private List<GrantedAuthority> roles = new ArrayList<GrantedAuthority>();

이런 인증/인가에 관련된 핵심적인 모델이라고 생각하면 된다. 즉 UserDetailService에서 이 UserDetail에 값을 채워줘야 한다. 

 

그럼 remember-me를 사용하기 위한 모든 준비는 끝이 났다. 


테스트

일단 크롬을 열어서 개발자도구를 열어준다. 

chrome cookie  확인

Application > Cookie tab으로 들어가서 Session을 볼 수 있도록 해주자. 로그인 화면만 열어서 일단 값이 없는 세션이 하나 들어간 것을 확인할 수 있따. 

 

그리고 로그인 화면에서 만든 remember-me 체크박스에 체크를 하고 로그인을 하자. 

remember-me

이걸 체크하고 로그인 한다는건 remember-me 기능을 활용하겠다는 것이다. 로그인!

 

remember-me 생성

로그인을 하면 아래에 remember-me라는 쿠키가 생성된것을 확인할 수 있다. 정상적으로 잘 생성이 되었다.

 

그럼 이제 유효한 세션을 날려보도록 하자. remember-me 아래에 JSESSIONID를 우클릭 하고 Delete 해준다. 

remember-me

그럼 이제 remember-me 쿠키만 남아있다. 이 상태에서 화면을 새로고침 해보자. 

 

remember-me로 세션 생성

그럼 새로운 유효한 세션이 생성이 되며 화면이 정상적으로 나온다. 

 

성공적으로 잘 적용이 되었다. 

 

끝!

댓글
최근에 올라온 글
최근에 달린 댓글
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31