본문 바로가기
Dev/SpringBoot

11. [springboot] 스프링부트 로그인 성공 이후 처리

by VIPeveloper 2020. 6. 12.
반응형

1. 서론

- 로그인 처리가 성공하였을 경우 처리에 대해 공부해보겠습니다.

 

- 일반 쇼핑몰 같은 경우, 로그인하지 않은 채 서비스들을 둘러보고 있다가, 결재하려 할 때 로그인 처리를 요구하는 경우가 있습니다. 이때, 로그인 시도 전 페이지를 캐싱하여 저장하고 있다가, 로그인 후 원래 보고 있었던 페이지로 이동할 수 있도록 하는 처리를 배워보도록 하겠습니다.

 

2. 본론

SecurityConfig.java

- 마찬가지로 환경 구성부터 실시합니다.

package com.example.springsecurity.security;

import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.security.servlet.PathRequest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationDetailsSource;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;

@Configuration
@EnableWebSecurity
@Slf4j
@AllArgsConstructor
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    private final AuthenticationSuccessHandler customSuccessHandler;

    private final AuthenticationDetailsSource authenticationDetailsSource;

    private final UserDetailsService userDetailsService;
    @Override
    public void configure(AuthenticationManagerBuilder auth) throws Exception {

//        String password = passwordEncoder().encode("1111");
//
//        auth.inMemoryAuthentication().withUser("user").password(password).roles("USER");
//        auth.inMemoryAuthentication().withUser("manager").password(password).roles("MANAGER");
//        auth.inMemoryAuthentication().withUser("admin").password(password).roles("ADMIN");
//        auth.userDetailsService(userDetailsService);
        auth.authenticationProvider(authenticationProvider());
    }

    @Bean
    public AuthenticationProvider authenticationProvider() {
        return new CustomAuthenticationProvider();
    }

    @Override
    // js, css, image 설정은 보안 설정의 영향 밖에 있도록 만들어주는 설정.
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().requestMatchers(PathRequest.toStaticResources().atCommonLocations());
    }

    @Bean
    // BCryptPasswordEncoder는 Spring Security에서 제공하는 비밀번호 암호화 객체입니다.
    // Service에서 비밀번호를 암호화할 수 있도록 Bean으로 등록합니다.
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                .antMatchers("/","/loginUser","/login*").permitAll()
                .antMatchers("/user").hasRole("USER")
                .antMatchers("/manager").hasRole("MANAGER")
                .antMatchers("/admin").hasRole("ADMIN")
                .anyRequest().authenticated()
            .and()
                .formLogin()
                .loginPage("/login")                    // controller mapping
                .loginProcessingUrl("/login_proc")      // th:action="@{/login_proc}"
                .authenticationDetailsSource(authenticationDetailsSource)   // 추가 파라메터 설정작업시, 설정해주기
                .defaultSuccessUrl("/")
                .successHandler(customSuccessHandler)	// 성공시 수행할 핸들러
                .permitAll();
    }


}

 

- .successHandler()로 처리해줍니다.

 

CustomAuthenticationSuccessHandler.java

package com.example.springsecurity.security;

import org.springframework.security.core.Authentication;
import org.springframework.security.web.DefaultRedirectStrategy;
import org.springframework.security.web.RedirectStrategy;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
import org.springframework.security.web.savedrequest.HttpSessionRequestCache;
import org.springframework.security.web.savedrequest.RequestCache;
import org.springframework.security.web.savedrequest.SavedRequest;
import org.springframework.stereotype.Component;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Component
public class CustomAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {

    private RequestCache requestCache = new HttpSessionRequestCache();

    private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
        // 쿠팡 둘러보기 하다가 로그인 성공 시 다시 거기로 가는 경우
        setDefaultTargetUrl("/");
        SavedRequest savedRequest = requestCache.getRequest(request,response);
        if(savedRequest != null){
            // 인증 받기 전 url로 이동하기
            String targetUrl = savedRequest.getRedirectUrl();
            redirectStrategy.sendRedirect(request,response,targetUrl);
        }else{
            // 기본 url로 가도록 함함
           redirectStrategy.sendRedirect(request,response,getDefaultTargetUrl());
        }
    }
}

- onAuthenticationSuccess 함수는 DI 시켜서 처리해줍니다. 캐시를 가져와서 null이 아닐 경우, 캐싱된 url로 이동하고, 아니면 기본 설정된 url로 이동하도록 처리합니다.

 

3. 결론

home.html에서 user 페이지로 이동하고자 하면 로그인 화면이 뜹니다. 이때, 로그인 화면이 뜨게 되는데, 정상적으로 입력하게 되면 다시 home.html로 이동하는 것이 아니라, user페이지로 바로 redirect 된다는 것이 이번 구현의 목적입니다.

4. 마무리

- 이상으로 로그인 성공 처리에 대해 알아보았습니다.

반응형