Spring/Spring Security

[Spring Security] Spring Security 설정하기

빅콜팝 2022. 10. 29. 00:57
728x90
반응형

Config 설정 클래스

import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;

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

@Configuration
@RequiredArgsConstructor
public class SecurityConfig {

    private final AuthenticationSuccess authenticationSuccess;
    private final AuthenticationFailure authenticationFailure;
    private final LogoutExecute logoutExecute;
    private final LogoutSuccess logoutSuccess;
    private final UserDetailsService userDetailsService;
    private final AuthenticationEntryException authenticationEntryException;
    private final AccessDeniedHandlerException accessDeniedHandlerException;

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
                .authorizeRequests() // 요청에 의한 보안검사 시작
                .anyRequest().authenticated(); //어떤 요청에도 보안검사를 한다.

        http.formLogin() // From 로그인 처리
                .loginPage("/member/login") // 사용자 정의 로그인 페이지
                .defaultSuccessUrl("/") // 로그인 성공 후 이동페이지
                .failureUrl("/login?error=true") // 로그인 실패 후 이동페이지
                .usernameParameter("userId") // 아이디 파라미터명
                .passwordParameter("password") // 비밀번호 파라미터명
                .loginProcessingUrl("/member/login") // 로그인 Form Action Url
                .successHandler(authenticationSuccess) // 로그인 성공 후 핸들러
                .failureHandler(authenticationFailure) // 로그인 실패 후 핸들러
                .permitAll() // .loginPage() 의 경로는 인증 없이 접근 가능
        ;
                
        http.logout() // 로그아웃 처리
                .logoutUrl("/member/logout") // 로그아웃 처리 URL(기본이 post)
                .logoutSuccessUrl("/") // 로그아웃 성공 URL
                .invalidateHttpSession(true) // 세션 무효화
                .deleteCookies("JSESSIONID") // 로그아웃 성공 시 제거할 쿠키명
                .addLogoutHandler(logoutExecute) // 로그아웃 핸들러
                .logoutSuccessHandler(logoutSuccess) // 로그아웃 성공 후 핸들러
        ; 
        
        http.exceptionHandling() // Exception 처리
                .authenticationEntryPoint(authenticationEntryException) // 인증 예외
                .accessDeniedHandler(accessDeniedHandlerException) // 인가 예외
        ;

        return http.build();
    }
    
    /**
     * 정적 자원 및 루트 페이지 ignore
     */
    @Bean
    public WebSecurityCustomizer webSecurityCustomizer() {
        return (web) -> web.ignoring()
                .requestMatchers(PathRequest.toStaticResources().atCommonLocations())
                .antMatchers("/", "/img/**", "/lib/**");
    }

}

 

/**
 * 로그인 성공 후 처리
 */
@Component
public class AuthenticationSuccess implements AuthenticationSuccessHandler {
    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {

        // AuthenticationException 발생 시 사용자의 요청 정보가 담긴 캐시가 세션에 저장됨 -> 로그인 성공 시 redirect
        RequestCache requestCache = new HttpSessionRequestCache();
        SavedRequest savedRequest = requestCache.getRequest(request, response);

        String redirectUrl = savedRequest.getRedirectUrl();
        response.sendRedirect(redirectUrl);

    }
}

 

Spring Security 제공 메서드 사용

인증 성공한 객체 정보 SecurityContextHolder.getContext().getAuthentication()
익명 사용자 isAnonymous() = ture
인증 사용자 isAuthenticated() = true
현재 사용자의 세션 만료 여부 체크 session.isExpired() = true

 

인증 / 인가 Exception 처리

인증 처리 예외 (신원 검증) AuthenticationException
인가 처리 예외 (권한 거부) AccessDeniedException

 

AuthenticationException(인증예외) 발생 시 AuthenticationEntryPoint 호출 (로그인 페이지 이동, 401 오류 코드 전달)

    - RequestCache : 추후 인증 성공 시 이전 요청 정보로 이동하기 위한 캐시 저장

    - SavedRequest : 사용자 요청 파라미터 및 헤더 정보

 

AccessDeniedException(인가예외) 발생 시 AccessDeniedHandler 호출 하여 예외 처리

 

/**
 *  인증 처리 예외 (신원 검증)
 *  RequestCache : 인증 성공 시 이전 요청 정보로 이동하기 위한 캐시 저장
 *  SavedRequest : 사용자 요청 파라미터 및 헤더 정보
 */
@Component
public class AuthenticationEntryPointException implements AuthenticationEntryPoint {
    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
        response.sendRedirect("/login");
    }
}

 

/**
 * 인가 처리 예외 (권한 거부)
 */
@Component
public class AccessDeniedHandlerException implements AccessDeniedHandler {
    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
        response.sendRedirect("/denied");
    }
}

 

728x90
반응형