2022년 5월 17일 TIL

yshjft·2022년 5월 17일
0

데브코스 TIL

목록 보기
33/45

Spring Security Architecture


Spring Security는 필터를 이용하여 웹 요청을 가로챈 후 사용자를 인증하고, 인증된 사용자가 적절한 권한을 지니고 있는지 확인한다.

AuthenticationManager
사용자 인증 관련 처리

AccessDecisionManager
사용자가 보호받는 리소스에 대한 접근할 수 있는 적절한 권한이 있는지 확인(인가)

사용자의 웹 요청 → DelegatingFilterProxy → springSecurityFilterChain (FilterChainProxy)

  • Spring Security의 실제적인 구현은 서블릿 필터 (javax.servlet.Filter 인터페이스 구현체) 를 통해 이루어져 있다.
  • 웹 요청은 모든 Security Filter를 차례로 통과하게 된다. 단 모든 필터가 동작하는 것은 아니다.

인증 요청에 의해 가로채어진 원래 요청으로 이동하기

AnonymousAuthenticationFilter

  • 익명사용자에 대한 처리를 하는 필터
  • 인증을 하지 않은 요청인 경우 인증 객체를 익명 권한이 들어가 있는 객체를 만들어 SecurityContextHolder에 넣어 주는 역할을 한다.
if (SecurityContextHolder.getContext().getAuthentication() == null) {
    Authentication authentication = this.createAuthentication((HttpServletRequest)req);
    SecurityContext context = SecurityContextHolder.createEmptyContext();
    context.setAuthentication(authentication);
    SecurityContextHolder.setContext(context);
    ...
            
}
  • AnonymousAuthenticationToken을 생성하여 SecurityFilter에서 null 대신 사용 한다.
protected Authentication createAuthentication(HttpServletRequest request) {
        AnonymousAuthenticationToken token = new AnonymousAuthenticationToken(this.key, this.principal, this.authorities);
        token.setDetails(this.authenticationDetailsSource.buildDetails(request));
        return token;
}
  • AnonymousAuthenticationFilter 커스텀
@Override
protected void configure(HttpSecurity http) throws Exception {
   http
        		
        ...
                
        .anonymous()
             .principal("thisIsAnonymousUser")
             .authorities("ROLE_ANONYMOUS", "ROLE_UNKNOWN")
             .and()
    ;
}

직접 커스텀하여 사용할 일은 거의 없는거 같다.

ExceptionTranslationFilter

FilterSecurityInterceptor

로그인 안한 상태에서 접근 거부가 일어나는 단계

FilterSecurityInterceptor에서 접근 거부 예외 발생
→ ExceptionTranslationFilter가 해당 예외(AccessDeniedException)를 catch하여 처리
→ if(isAnonymous) {sendStartAuthentication()}
→ requestCache.saveRequest()를 통해 원래 접근하려고 하였던 페이지(요청) 저장

로그인
RequestCacheAwareFilter에서 this.requestCache.getMatchingRequest()를 통해 저장되었던 원래 요청 가지고 온다.

FilterSecurityInterceptor
필터 체인 상에서 FilterSecurityInterceptorExceptionTranslationFilter의 바로 아래에 위치한다. 따라서 FilterSecurityInterceptor 실행 중 발생할 수 있는 예외(AuthenticationException, AccessDeniedException)를 ExceptionTranslationFilter에서 처리한다. 이는 커스텀 필터에서 발생하는 예외를 ExceptionTranslationFilter에서 처리하기 위해서는 커스텀 필터가 ExceptionTranslationFilter에 위치해야함을 의미한다.

AuthenticationEntryPoint

  • 인증되지 않은 사용자 요청을 처리할때 핵심 적인 역할을 수행한다.(ex. 사용자를 로그인 요청 페이지로 포워딩 하는 역할)

SpringSecurity 예외 처리 과정 요약

Filter Chain에서 예외 발생
ExceptionTransalationFilter가 예외를 catch

Is AuthenticationException?
requet를 캐싱하고 AuthenticationEntryPoint를 이용하여 사용자를 로그인 페이지로 포워딩

Is AccessDeniedException? OR Remember-me 인증?
Anonymous User인지 확인하고 만약 맞다면 기존 요청을 캐싱하고 사용자를 로그인 페이지로 포워딩한다. 만약 아니라면 AccessDeniedHanlder가 실행된다.

custom accessDeniedHandler

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
    		
            ...
            
            .exceptionHandling()
                .accessDeniedHandler(accessDeniedHandler());

    ;
}

@Bean
public AccessDeniedHandler accessDeniedHandler() {
    return (request, response, e) -> {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        Object principal = authentication != null ? authentication.getPrincipal() : null;
        log.warn("{} is denied", principal, e);

        response.setStatus(HttpServletResponse.SC_FORBIDDEN);
        response.setContentType("text/plain");
        response.getWriter().write("## ACCESS DENIED ##");
        response.getWriter().flush();
        response.getWriter().close();
    };
}
  • HTTP 403 응답 생성

전송 레이어 보안 적용

application.yml을 통한 포트 변경 & server.ssl 설정

server:
  port: 443
  ssl:
    enabled: true
    key-alias: prgrms_keystore
    key-store: classpath:prgrms_keystore.p12
    key-store-password: prgrms123
    key-password: prgrms123
    trust-store: classpath:prgrms_truststore.p12
    trust-store-password: prgrms123

ChannelProcessingFilter

ChannelProcessingFilter 설정을 통해 HTTPS 채널을 통해 처리해야 하는 웹 요청을 정의할 수 있다.

@Configuration
@EnableWebSecurity
public class WebSecurityConfigure extends WebSecurityConfigurerAdapter {
	
    ...
    
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
        		...
                
                .requiresChannel()
                .anyRequest().requiresSecure()
        ;
    }
}

대칭 키 암호화 및 SSL

RSA 암호화

  • 사실상 표준 공개키 암호 알고리즘
  • 공개키와 개인키가 한 쌍을 이루며, 공개키로 암호화한 내용은 개인키로만, 개인키로 암호화한 내용은 공개키로만 해독할 수 있는 암호화 방식
  • 공개 키 암호화
  • SSL
profile
꾸준히 나아가자 🐢

0개의 댓글