SpringSecurity 란?
Spring Security는 스프링 프레임워크(Spring Framework)에서 제공하는 보안 프레임워크로, 애플리케이션의 인증 및 권한 부여를 처리하는 데 사용됩니다. Spring Security는 강력한 인증 및 접근 제어 기능을 제공하며, 애플리케이션을 다양한 공격으로부터 보호하는 데 중요한 역할을 합니다.
springsecuirty 는 사용해본 분들은 아시겠지만 편하고 검증된 보안기능을 빠르게 개발할 수 있는 라이브러리 입니다. 지금까지는 저도 단순하게 security를 사용하는데 급급했지만 시간이 남을때 좀 더 자세히 정리해 놓는게 좋을 듯 하여 구조와 라이프 사이클에 대해 정리해볼까 합니다.
JWT 적용을 위한 SpringSecurity
아래 그림은 기본적인 login에 대한 인가는 제외한 jwt 만을 적용하기 위한 구조로서 생성된 custom class 위주의 그림입니다.
좀 더 디테일한 부분에 있어서는 조금씩 채워 나가도록 하겠습니다.
개발자의 입장에서 springsecurity의 개발 순서 및 간단한 샘플을 공유해보겠습니다.
위 스크린샷의 오른쪽 사진은 실행되는 filter들의 목록입니다.
제가 추가한 것도 있지만 기본적으로 여러 필터들을 거쳐갑니다.
※ version을 항상 체크하시기 바랍니다. 사용하고 있는 method들이 언제 deprecated 될지 모르니까요 ;
1. SecurityConfig 클래스 생성 및 설정
springsecurty 사용을 위한 config 클래스를 생성하고 그 내용을 채워줍니다.
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private CustomAccessDecisionManager accessDecisionManager;
// 모든 웹 요청에 대해 인증된 사용자만 접근 허용
// JWTlogging필터 추가
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests()
.anyRequest()
.authenticated()
.and()
.addFilterBefore(new CustomLoggingFilter(), UsernamePasswordAuthenticationFilter.class);
}
}
2. CustomFilter 클래스 생성
JWT 를 검증하고 인가작업을 진행하기 위한 CustomFilter 클래스를 생성하고 내용을 만들어 줍니다.
필요에 따라 대상이 되는 기본 Filter의 시작시점 전,후로 배치하거나 교체 할 수 있습니다.
이번 예제에서는 전 단계에서 실행합니다.
public class CustomLoggingFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
// 인증 및 인가 후에 로깅 작업을 수행
System.out.println("Request processed by CustomLoggingFilter");
chain.doFilter(request, response);
}
}
3. ExceptionHandling 클래스 생성
인증에 대한 예외가 발생 했을때는 AuthenticationEntryPoint 인터페이스의 commece가 호출 되고
인가에 대한 예외가 발생했을때는 AccessDeniedHandler의 handle 메소드가 호출 됩니다.
// AuthenticationEntryPoint
/**
* Used by {@link ExceptionTranslationFilter} to commence an authentication scheme.
*
* @author Ben Alex
*/
public interface AuthenticationEntryPoint {
/**
* Commences an authentication scheme.
* <p>
* <code>ExceptionTranslationFilter</code> will populate the <code>HttpSession</code>
* attribute named
* <code>AbstractAuthenticationProcessingFilter.SPRING_SECURITY_SAVED_REQUEST_KEY</code>
* with the requested target URL before calling this method.
* <p>
* Implementations should modify the headers on the <code>ServletResponse</code> as
* necessary to commence the authentication process.
* @param request that resulted in an <code>AuthenticationException</code>
* @param response so that the user agent can begin authentication
* @param authException that caused the invocation
*/
void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException)
throws IOException, ServletException;
}
// custom 구현체
@Component
@RequiredArgsConstructor
public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint{
private JwtTokenProvider jwtTokenProvider;
@Override
public void commence(HttpServletRequest request, HttpServletResponse response,
AuthenticationException authException) throws IOException, ServletException {
String accessToken = jwtTokenProvider.resolveToken(request);
// accessToken이 만료 되었을 경우 작업처리
}
}
jwt를 사용하기 위한 기본이 되는 springsecurity 에 대해 체크를 해봤습니다.
사실 아직 갈길이 멀긴 합니다만, spring 자체에서 거의 대부분의 작업들을 해주기때문에
사용자는 필터에 대한 이해와 어떤 메커니즘으로 방향을 잡을지만 정하면 될 것 같습니다.