Spring Security 는 Spring 기반 애플리케이션의 인증(Authentication)과 인가(Authorization)를 담당하는 강력한 보안 프레임워크이다. 주로 웹 애플리케이션의 보안을 강화하는 데 사용되며, 다양한 인증 방식과 접근 제어 기능을 제공한다.
Spring Security 는 Filter 기반으로 Spring MVC 와 분리되어 관리 및 동작한다.
→ 로그인 (ID/Password, OAuth, JWT)
→ 권한
Spring Security (2003) 👉 JWT 스펙 적용 (2018)
Spring Security 대부분의 스펙이 세션 방식을 기반으로 개발
Stateless 인증: 서버가 사용자 인증 상태를 저장하지 않고 JWT 토큰으로 인증을 처리
JwtAuthenticationTokenpublic class JwtAuthenticationToken extends AbstractAuthenticationToken {
private final AuthUser authUser;
public JwtAuthenticationToken(AuthUser authUser) {
super(authUser.getAuthorities());
this.authUser = authUser;
setAuthenticated(true);
}
@Override
public Object getCredentials() {
return null; // session 스펙
}
@Override
public Object getPrincipal() {
return authUser;
}
}
JwtAuthenticationFilter private void setAuthentication(Claims claims) {
Long userId = Long.valueOf(claims.getSubject());
String email = claims.get("email", String.class);
UserRole userRole = UserRole.of(claims.get("userRole", String.class));
AuthUser authUser = new AuthUser(userId, email, userRole);
JwtAuthenticationToken authenticationToken = new JwtAuthenticationToken(authUser);
SecurityContextHolder.getContext().setAuthentication(authenticationToken);
}
SecurityConfig@Configuration
@RequiredArgsConstructor
@EnableWebSecurity
@EnableMethodSecurity(securedEnabled = true)
public class SecurityConfig {
// @EnableMethodSecurity => @Secured 사용 가능
private final JwtAuthenticationFilter jwtAuthenticationFilter;
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
return http
.csrf(AbstractHttpConfigurer::disable)
.sessionManagement(session -> session
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
) // stateless 인증
.addFilterBefore(jwtAuthenticationFilter, SecurityContextHolderAwareRequestFilter.class)
.formLogin(AbstractHttpConfigurer::disable) // 폼로그인 비활성화
.anonymous(AbstractHttpConfigurer::disable) // 익명사용자 권한 비활성화
.httpBasic(AbstractHttpConfigurer::disable) // BasicAuthenticationFilter 비활성화
.logout(AbstractHttpConfigurer::disable) // 로그아웃 비활성화 -> 클라이언트가 JWT 삭제
.rememberMe(AbstractHttpConfigurer::disable) // RememberMeAuthenticationFilter 비활성화
.authorizeHttpRequests(auth -> auth
.requestMatchers(request -> request.getRequestURI().startsWith("/auth")).permitAll()
.requestMatchers("/test").hasAuthority(UserRole.Authority.ADMIN)
.anyRequest().authenticated()
)
.build();
}
}