spring security+jwt 사용하기

지혜·2025년 3월 17일
0

📝스프링 시큐리티

Spring Security는 Spring Framework 기반의 보안 프레임워크로, 애플리케이션의 인증(Authentication) 및 권한 부여(Authorization) 기능을 제공

1. 주요 기능

  • 인증(Authentication): 로그인 등 사용자의 신원을 확인하는 과정
  • 인가(Authorization): 사용자의 접근 권한을 확인하는 과정
  • CSRF방어: 정상적인 요청인지 확인
  • 세션 관리: 새션의 생성, 유지, 종료 관리
  • OAuth 2.0 / JWT 지원: 토큰 기반 인증을 쉽게 구현할 수 있도록 지원

2. 스프링 시큐리티의 핵심 개념

  • SecurityFilterChain
    • 스프링 시큐리티는 여러 개의 보안 필터를 체인 형태로 연결하여 동작
    • 요청이 들어오면 SecurityFilterChain에서 검증 후 컨트롤러에 전달됨.
        @Bean
      public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
          return http
                  .csrf(AbstractHttpConfigurer::disable) // CSRF 비활성화
                  .sessionManagement(session -> session
                          .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                  ) // jwt 사용을 위해 session 비활성화
                  .addFilterBefore(jwtAuthenticationFilter, SecurityContextHolderAwareRequestFilter.class) // jwt 필터 사용
                  .formLogin(AbstractHttpConfigurer::disable) // login 비활성화
                  .anonymous(AbstractHttpConfigurer::disable) // 익명 사용자 비활성화
                  .httpBasic(AbstractHttpConfigurer::disable) // 기본 인증 비활성화
                  .logout(AbstractHttpConfigurer::disable) // 로그아웃 비활성화
                    .rememberMe(AbstractHttpConfigurer::disable) // 권한 기억하기 기능 비활성화
                  .authorizeHttpRequests(auth -> auth
                          .requestMatchers(request -> request.getRequestURI().startsWith("/auth")).permitAll() // "/auth"의 경우 모든 사용자 접근 가능
                          .requestMatchers("/admin/**").hasAuthority(UserRole.Authority.ADMIN) // "ADMIN"권한을 가진 사용자만 접근 가능
                          .anyRequest().authenticated() // 그외 요청 인증 필요
                  )
                  .build();
      }

🤔 왜 보안기능을 비활성화 할까?

  • CSRF : JWT 사용 시 불필요

  • 세션 : JWT는 무상태(StateLess) 인증을 사용하기 때문에 session 불필요

  • 폼 로그인/기본 인증 비활성화 → JWT를 사용 시 불필요

  • 익명/로그아웃/기억하기 기능 비활성화 → JWT 인증 방식과 맞지 않음

  • 인증 (Authentication)

    • 사용자의 로그인 정보를 검증하는 과정
    • security는 기본적으로 session기반 의 UsernamePasswordAuthenticationToken을 사용
    • 그 밖의 OAuth2, JWT, LDAP 등 인증 방식 지원
  • 권한 부여 (Authorization)
    • 특정 권한을 가진 사용에게만 특정 리소스에 접근하도록 허용하는 과정
    • @PreAuthorize, @Secured 등을 사용하여 권한을 설정

      🤔 @PreAuthorize vs @Secured
      @Secured : @Secured는 역할만 체크, 사용시 ROLE_권한형식으로 지정
      @PreAuthorize : 스프링 시큐리티의 표현식(SpEL, Spring Expression Language)을 사용할 수 있어 더 유연, hasRole()을 사용할 경우 "ROLE_"을 생략

@Secured(UserRole.Authority.ADMIN)
@PatchMapping("/admin/users/{userId}")
public void changeUserRole(@PathVariable long userId, @RequestBody UserRoleChangeRequest userRoleChangeRequest) {
    userAdminService.changeUserRole(userId, userRoleChangeRequest);
}
  • UserDetailsService

    • session 기반의 security 적용
    • 사용자 정보를 로드하는 인터페이스
    • DB에서 사용자 정보를 불러와 인증을 수행할 때 사용
  • PasswordEncoder

    • 비밀번호를 암호화하는 인터페이스 (ex BCryptPasswordEncoder 등)
    • matches(rawPassword, encodedPassword)로 비밀번호 검증
    import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
    
    @Bean
      public PasswordEncoder passwordEncoder() {
          return new BCryptPasswordEncoder();
      }

jwt란?

  • 토큰 기반 인증 방식 서버가 세션을 저장하지 않고 인증
  • 무상태 인증(Stateless) 인증 방식, 요청할 때마다 토큰을 전달

📌 JWT방식 적용하기

  • SpringContextPersistenceFilter 에서 매 요청마다 빈(empty) SecurityContext를 생성
    .sessionManagement(session -> session
    .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
    )

📌 **기존 session제거**
```java
.formLogin(AbstractHttpConfigurer::disable)
.anonymous(AbstractHttpConfigurer::disable)
.httpBasic(AbstractHttpConfigurer::disable)
.logout(AbstractHttpConfigurer::disable)
.rememberMe(AbstractHttpConfigurer::disable)

📌 userRole를 리스트로 설정

  • 유저의 권한이 1개 이상일 수 있기 때문에
  • ex) 게임의 경우 user, tester인 경우
    public AuthUser(Long id, String email, UserRole role) {
        this.id = id;
        this.email = email;
        this.authorities = List.of(new SimpleGrantedAuthority(role.name()));
    }

✅ 결론

  • Spring Security는 인증과 권한을 부여하는 프레임워크
  • 기본적으로 session방식을 지원하므로 jwt를 이용시 세션 방식 제거 필요
  • SecurityFilterChain을 이용하여 보안 필터 적용
  • @Secured, @PreAuthorize 활용하여 권한 관리
  • 비밀번호는 PasswordEncoder로 암호화
  • 유저의 역할(ROLE)은 리스트로 관리하여 확장성 고려

0개의 댓글

관련 채용 정보