programing

스프링 부트 3의 스프링 보안

cafebook 2023. 7. 22. 10:24
반응형

스프링 부트 3의 스프링 보안

현재 REST 애플리케이션을 Spring Boot 2.7.5에서 3.0.0-RC2로 마이그레이션하는 중입니다.Open API URL을 제외한 모든 것이 안전했으면 합니다. Spring Boot 2.7.5에서는 다음과 같이 작업했습니다.

@Named
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests()
        .antMatchers("/openapi/openapi.yml").permitAll()
        .anyRequest().authenticated()
        .and()
        .httpBasic();
  }
}

그리고 잘 작동했습니다.Spring Boot 3에서, 나는 그것을 바꾸어야 했습니다.

@Configuration
@EnableWebSecurity
public class WebSecurityConfig {

  @Bean
  public SecurityFilterChain configure(HttpSecurity http) throws Exception {
    http.authorizeHttpRequests((requests) -> requests
            .requestMatchers("/openapi/openapi.yml").permitAll()
            .anyRequest()
            .authenticated())
        .httpBasic();

    return http.build();
  }
}

WebSecurityConfigurerAdapter가 제거되었기 때문입니다.그런데 안 되네요.Open API URL도 기본 인증을 통해 보호됩니다.제가 코드를 업그레이드할 때 실수를 한 것입니까, 아니면 스프링 부트 3 RC 2에서 문제가 발생한 것입니까?

업데이트 새 API의 대부분이 2.7.5에서 이미 사용 가능했기 때문에 2.7.5 코드 기반의 코드를 다음과 같이 업데이트했습니다.

@Configuration
@EnableWebSecurity
public class WebSecurityConfig {

  @Bean
  public SecurityFilterChain configure(HttpSecurity http) throws Exception {
    http
        .csrf().disable()
        .authorizeHttpRequests((requests) -> requests
            .antMatchers(OPTIONS).permitAll() // allow CORS option calls for Swagger UI
            .antMatchers("/openapi/openapi.yml").permitAll()
            .anyRequest().authenticated())
        .httpBasic();
    return http.build();
  }
}

3.0.0-RC2 지점에서 코드는 다음과 같습니다.

@Configuration
@EnableWebSecurity
public class WebSecurityConfig {

  @Bean
  public SecurityFilterChain configure(HttpSecurity http) throws Exception {
    http
        .csrf().disable()
        .authorizeHttpRequests((requests) -> requests
            .requestMatchers(OPTIONS).permitAll() // allow CORS option calls for Swagger UI
            .requestMatchers("/openapi/openapi.yml").permitAll()
            .anyRequest().authenticated())
        .httpBasic();
    return http.build();
  }
}

보시다시피, 유일한 차이점은 제가 개미Matchers 대신 requestMatchers를 호출한다는 것입니다.이 메서드의 이름이 변경된 것 같습니다.methodantMatchers를 더 이상 사용할 수 없습니다.그러나 최종 효과는 여전히 동일합니다.3.0.0-RC2용 지점에서 Spring Boot은 Open에 대한 기본 인증을 요청합니다.API URL. 2.7.5에서 여전히 작동합니다.

작성자: https://github.com/wilkinsona

  @Bean
  public SecurityFilterChain configure(HttpSecurity http) throws Exception {
    http
        .authorizeHttpRequests(requests -> requests
            .requestMatchers(new AntPathRequestMatcher("/openapi/openapi.yml")).permitAll()
            .anyRequest().authenticated())
        .httpBasic();
    return http.build();
  }

출처: https://github.com/spring-projects/spring-boot/issues/33357#issuecomment-1327301183

지금은 RC 버전이 아닌 스프링 부트 3.0.0(GA)을 사용하는 것을 추천합니다.

WebSecurityConfig에서 다음 작업을 수행했습니다.

private static final String[] AUTH_WHITELIST = {
        // -- Swagger UI v2
        "/v2/api-docs",
        "v2/api-docs",
        "/swagger-resources",
        "swagger-resources",
        "/swagger-resources/**",
        "swagger-resources/**",
        "/configuration/ui",
        "configuration/ui",
        "/configuration/security",
        "configuration/security",
        "/swagger-ui.html",
        "swagger-ui.html",
        "webjars/**",
        // -- Swagger UI v3
        "/v3/api-docs/**",
        "v3/api-docs/**",
        "/swagger-ui/**",
        "swagger-ui/**",
        // CSA Controllers
        "/csa/api/token",
        // Actuators
        "/actuator/**",
        "/health/**"
};

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    return http
            .csrf(AbstractHttpConfigurer::disable)
            .authorizeHttpRequests( auth -> auth
                    .requestMatchers(AUTH_WHITELIST).permitAll()
                    .anyRequest().authenticated()
            )
            .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
            .httpBasic(withDefaults())
            .addFilterBefore(authenticationJwtTokenFilter, UsernamePasswordAuthenticationFilter.class)
            //.addFilterAfter(authenticationJwtTokenFilter, UsernamePasswordAuthenticationFilter.class)
            .build();
}

@Bean
public SecurityFilterChain configure(HttpSecurity httpSecurity) throws Exception {
    httpSecurity
            .authorizeHttpRequests((requests) -> requests
                    .requestMatchers( new AntPathRequestMatcher("swagger-ui/**")).permitAll()
                    .requestMatchers( new AntPathRequestMatcher("/swagger-ui/**")).permitAll()
                    .requestMatchers( new AntPathRequestMatcher("v3/api-docs/**")).permitAll()
                    .requestMatchers( new AntPathRequestMatcher("/v3/api-docs/**")).permitAll()
                    .anyRequest().authenticated())
            .httpBasic();
    return httpSecurity.build();
}

이 작업 및 도커 파일 사용(실행)mvn clean package그리고 Docker에서 .jar를 실행)을 실행하면 스웨거 UI 내부의 인증에 문제가 없습니다.

이것이 당신에게 도움이 되기를 바랍니다 :)

사용하다

  http.securityMatcher("<patterns>")...

엔드포인트에 대한 인증을 지정합니다.

      authorizeHttpRequests((requests) -> requests
                .requestMatchers("<pattern>")

설정하지 않은 경우 인증에만 작동합니다.securityMatcherSecurityFilterChain은 기본적으로 다음을 가져옵니다.any request인증용입니다.모든 요청은 인증 공급자에 의해 인증됩니다.

이 경우 두 개의 보안 필터 체인을 정의할 수 있습니다. 하나는 공용 엔드포인트용이고 다른 하나는 보안용입니다.그리고 그들에게 적절한 명령을 내립니다.

    @Bean
    @Order(1)
    public SecurityFilterChain configurePublicEndpoints(HttpSecurity http) throws Exception {
        http.securityMatcher(OPTIONS,"/openapi/openapi.yml").csrf().disable()
            .authorizeHttpRequests((requests) -> requests
                .anyRequest().permitAll() // allow CORS option calls for Swagger UI
    );
        return http.build();
      }
    
    @Bean
    Order(2)
      public SecurityFilterChain configure(HttpSecurity http) throws Exception {
        http.securityMatcher("/**")
            .csrf().disable()
            .authorizeHttpRequests((requests) -> requests.anyRequest().authenticated())
            .httpBasic();
        return http.build();
      }

내 보안 cfg는 다음과 같습니다.

스프링 3.0.0

@Bean
public SecurityFilterChain configure(HttpSecurity http) throws Exception {
    http
        .csrf().disable()
        .authorizeHttpRequests(requests -> requests
                .requestMatchers(HttpMethod.GET, "/", "/static/**", "/index.html", "/api/users/me").permitAll()
                .requestMatchers(HttpMethod.POST, "/api/users").permitAll()
                .requestMatchers(HttpMethod.GET, "/api/users/login", "/api/users/{username}", "/api/users/logout", "/api/customers", "/api/storages").authenticated()
                .requestMatchers(HttpMethod.POST, "/api/customers", "/api/storages").authenticated()
                .requestMatchers(HttpMethod.PUT, "/api/customers/{id}", "/api/storages/{id}").authenticated()
                .requestMatchers(HttpMethod.DELETE, "/api/users/{id}", "/api/storages/{id}", "/api/customers/{id}").authenticated()
                .anyRequest().denyAll())
        .httpBasic();
    return http.build();
}

그건 효과가 있다.

공식 문서에는 다음과 같은 구성의 예가 나와 있습니다.

http
  .authorizeExchange((exchanges) ->
    exchanges
      .pathMatchers("/openapi/openapi.yml").permitAll()
      .anyExchange().authenticated())
    .httpBasic();

return http.build();

선언적 클라이언트로의 마이그레이션에 따라 "교환" 문구에 대한 "요청"이 변경되므로 시도해 볼 수 있습니다(@PostExchange vs. @PostMapping).도움이 되길 바랍니다.

보안 구성은 다음과 같습니다.

스프링 3.1.1

   http.csrf(httpSecurityCsrfConfigurer -> httpSecurityCsrfConfigurer.disable())
                .authorizeHttpRequests((requests) -> requests
                        .requestMatchers("/swagger-ui/**").permitAll()
                        .anyRequest().authenticated())
                .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
                .headers(httpSecurityHeadersConfigurer -> httpSecurityHeadersConfigurer.frameOptions(frameOptionsConfig -> frameOptionsConfig.disable())) //to make accessible h2 console, it works as frame
                .exceptionHandling(httpSecurityExceptionHandlingConfigurer -> httpSecurityExceptionHandlingConfigurer.authenticationEntryPoint(new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED)))
                .addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);

return http.build();

이것은 Spring Boot 3의 버그인 것 같습니다.제가 문제를 제기했습니다.

언급URL : https://stackoverflow.com/questions/74447778/spring-security-in-spring-boot-3

반응형