Spring Security DefaultSecurityFilterChain 在 GKE 中部署时未应用 BearerTokenAuthenticationFilter

问题描述 投票:0回答:1

我正在开发一个 Java Springboot 服务,该服务托管在 Google Cloud Platform 上的 GKE 中。我正在使用 OAuth2.0 授权对服务端点的请求。

  • Java 17
  • Springboot 3.2.4

当我在本地运行服务时,Spring 的 DefaultSecurityChain 正确包含 BearerTokenAuthenticationFilter,并且如果请求具有有效的承载令牌,则允许该请求。 当我在 GKE 中部署并运行该服务时,它不包含过滤器,并且所有请求都被拒绝。

我有一个配置类,我在其中定义了以下filterChain。

@Configuration
@EnableMethodSecurity
public class AuthConfig {
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.csrf(csrf -> csrf.disable());
        http.authorizeHttpRequests(authorize -> authorize.anyRequest().authenticated()).oauth2ResourceServer(oauth2 -> oauth2.jwt(Customizer.withDefaults()));
        return http.build();
    }

在 application.properties 中我设置了以下属性:

spring.security.oauth2.resourceserver.jwt.cloak-skew
spring.security.oauth2.resourceserver.jwt.issuer-uri
spring.security.oauth2.resourceserver.jwt.jwk-set-uri
spring.security.oauth2.client.provider.<my_provider>.token-uri

我还临时设置了这些以公开其他日志以进行故障排除:

logging.level.org.springframework.web=TRACE
logging.level.org.springframework.security=TRACE
spring.mvc.log-request-details=true

当服务运行时本地Spring 会向日志输出以下内容:

 Trying to match request against DefaultSecurityFilterChain 
 [
 RequestMatcher=any request,
 Filters=[
 org.springframework.security.web.session.DisableEncodeUrlFilter,
 org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter,
 org.springframework.security.web.context.SecurityContextHolderFilter,
 org.springframework.security.web.header.HeaderWriterFilter,
 org.springframework.web.filter.CorsFilter,
 org.springframework.security.web.authentication.logout.LogoutFilter,
 org.springframework.security.oauth2.server.resource.web.authentication.BearerTokenAuthenticationFilter,
 org.springframework.security.web.savedrequest.RequestCacheAwareFilter,
 org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter,
 org.springframework.security.web.authentication.AnonymousAuthenticationFilter,
 org.springframework.security.web.access.ExceptionTranslationFilter,
 org.springframework.security.web.access.intercept.AuthorizationFilter]] (1/1)

当服务运行时在 GKE 中 Spring 会向日志输出以下内容:

 Trying to match request against DefaultSecurityFilterChain 
 [
 RequestMatcher=any request, 
 Filters=[
 org.springframework.security.web.session.DisableEncodeUrlFilter,
 org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter,
 org.springframework.security.web.context.SecurityContextHolderFilter,
 org.springframework.security.web.header.HeaderWriterFilter,
 org.springframework.web.filter.CorsFilter,
 org.springframework.security.web.authentication.logout.LogoutFilter,
 org.springframework.security.web.savedrequest.RequestCacheAwareFilter,
 org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter,
 org.springframework.security.web.authentication.AnonymousAuthenticationFilter,
 org.springframework.security.web.access.ExceptionTranslationFilter,
 org.springframework.security.web.access.intercept.FilterSecurityInterceptor]] (1/1)

所有本地日志:

[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'
o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
o.s.web.servlet.DispatcherServlet        : Detected org.springframework.web.multipart.support.StandardServletMultipartResolver
o.s.web.servlet.DispatcherServlet        : Detected org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver
o.s.web.servlet.DispatcherServlet        : Detected org.springframework.web.servlet.theme.FixedThemeResolver
o.s.web.servlet.DispatcherServlet        : Detected DefaultRequestToViewNameTranslator
o.s.web.servlet.DispatcherServlet        : Detected SessionFlashMapManager
o.s.web.servlet.DispatcherServlet        : enableLoggingRequestDetails='true': request parameters and headers will be shown which may lead to unsafe logging of potentially sensitive data
o.s.web.servlet.DispatcherServlet        : Completed initialization in 4 ms
 o.s.security.web.FilterChainProxy        : Trying to match request against DefaultSecurityFilterChain <see above for where I've provided this>
o.s.security.web.FilterChainProxy        : Securing GET /<my_endpoint>/?<param1>=<value1>&<param2>=<value2>
o.s.security.web.FilterChainProxy        : Invoking DisableEncodeUrlFilter (1/12)
o.s.security.web.FilterChainProxy        : Invoking WebAsyncManagerIntegrationFilter (2/12)
o.s.security.web.FilterChainProxy        : Invoking SecurityContextHolderFilter (3/12)
o.s.security.web.FilterChainProxy        : Invoking HeaderWriterFilter (4/12)
o.s.security.web.FilterChainProxy        : Invoking CorsFilter (5/12)
o.s.security.web.FilterChainProxy        : Invoking LogoutFilter (6/12)
o.s.s.w.a.logout.LogoutFilter            : Did not match request to Or [Ant [pattern='/logout', GET], Ant [pattern='/logout', POST], Ant [pattern='/logout', PUT], Ant [pattern='/logout', DELETE]]

o.s.security.web.FilterChainProxy        : Invoking BearerTokenAuthenticationFilter (7/12)
o.s.s.authentication.ProviderManager     : Authenticating request with JwtAuthenticationProvider (1/2)
o.s.web.client.RestTemplate              : HTTP GET https://<JWK_URL>
o.s.web.client.RestTemplate              : Accept=[text/plain, application/json, application/*+json, */*]
o.s.web.client.RestTemplate              : Response 200 OK
o.s.web.client.RestTemplate              : Reading to [java.lang.String] as "application/json;charset=utf-8"
s.o.s.r.a.JwtGrantedAuthoritiesConverter : Looking for scopes in claim scope
o.s.s.o.s.r.a.JwtAuthenticationProvider  : Authenticated token
.s.r.w.a.BearerTokenAuthenticationFilter : Set SecurityContextHolder to JwtAuthenticationToken [Principal=org.springframework.security.oauth2.jwt.Jwt@da27f0e1, Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=<some_IP>, SessionId=null], Granted Authorities=[SCOPE_<the_required_scope>]]
o.s.security.web.FilterChainProxy        : Invoking RequestCacheAwareFilter (8/12)
o.s.s.w.s.HttpSessionRequestCache        : matchingRequestParameterName is required for getMatchingRequest to lookup a value, but not provided
o.s.security.web.FilterChainProxy        : Invoking SecurityContextHolderAwareRequestFilter (9/12)
o.s.security.web.FilterChainProxy        : Invoking AnonymousAuthenticationFilter (10/12)
o.s.security.web.FilterChainProxy        : Invoking ExceptionTranslationFilter (11/12)
o.s.security.web.FilterChainProxy        : Invoking AuthorizationFilter (12/12)
estMatcherDelegatingAuthorizationManager : Authorizing SecurityContextHolderAwareRequestWrapper[ org.springframework.security.web.header.HeaderWriterFilter$HeaderWriterRequest]
estMatcherDelegatingAuthorizationManager : Checking authorization on SecurityContextHolderAwareRequestWrapper[ org.springframework.security.web.header.HeaderWriterFilter$HeaderWriterRequest] using org.springframework.security.authorization.AuthenticatedAuthorizationManager
o.s.s.w.a.AnonymousAuthenticationFilter  : Did not set SecurityContextHolder since already authenticated JwtAuthenticationToken [Principal=org.springframework.security.oauth2.jwt.Jwt, Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=<some_IP>, SessionId=null], Granted Authorities=[SCOPE_<the_required_scope>]]
o.s.security.web.FilterChainProxy        : Secured GET /<my_endpoint>/?<param1>=<value1>&<param2>=<value2>
logging.WebApiLoggingFilter  : Server request: method=GET uri=/<my_endpoint>/?<param1>=<value1>&<param2>=<value2>
o.s.web.servlet.DispatcherServlet        : GET "/<my_endpoint>/?<param1>=<value1>&<param2>=<value2>", parameters={<param1>:<value1>, <param2>:<value2>}, headers={authorization:[Bearer <bearer_token>], user-agent:[PostmanRuntime/7.43.0], accept:[*/*], cache-control:[no-cache], postman-token:[<some_token>], host:[localhost:8080], accept-encoding:[gzip, deflate, br], connection:[keep-alive]} in DispatcherServlet 'dispatcherServlet'

所有 GKE 日志:

[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'
o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
o.s.web.servlet.DispatcherServlet        : Detected org.springframework.web.multipart.support.StandardServletMultipartResolver
o.s.web.servlet.DispatcherServlet        : Detected org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver
o.s.web.servlet.DispatcherServlet        : Detected org.springframework.web.servlet.theme.FixedThemeResolver
o.s.web.servlet.DispatcherServlet        : Detected DefaultRequestToViewNameTranslator
o.s.web.servlet.DispatcherServlet        : Detected SessionFlashMapManager
o.s.web.servlet.DispatcherServlet        : enableLoggingRequestDetails='true': request parameters and headers will be shown which may lead to unsafe logging of potentially sensitive data
o.s.web.servlet.DispatcherServlet        : Completed initialization in 4 ms
o.s.security.web.FilterChainProxy        : Trying to match request against DefaultSecurityFilterChain <see above for where I've provided this>
o.s.security.web.FilterChainProxy        : Securing GET /<my_endpoint>/?<param1>=<value1>&<param2>=<value2>
o.s.security.web.FilterChainProxy        : Invoking DisableEncodeUrlFilter (1/11)
o.s.security.web.FilterChainProxy        : Invoking WebAsyncManagerIntegrationFilter (2/11)
o.s.security.web.FilterChainProxy        : Invoking SecurityContextHolderFilter (3/11)
o.s.security.web.FilterChainProxy        : Invoking HeaderWriterFilter (4/11)
o.s.security.web.FilterChainProxy        : Invoking CorsFilter (5/11)
o.s.security.web.FilterChainProxy        : Invoking LogoutFilter (6/11)
o.s.s.w.a.logout.LogoutFilter            : Did not match request to Or [Ant [pattern='/logout', GET], Ant [pattern='/logout', POST], Ant [pattern='/logout', PUT], Ant [pattern='/logout', DELETE]]
o.s.security.web.FilterChainProxy        : Invoking RequestCacheAwareFilter (7/11)
o.s.s.w.s.HttpSessionRequestCache        : matchingRequestParameterName is required for getMatchingRequest to lookup a value, but not provided
o.s.security.web.FilterChainProxy        : Invoking SecurityContextHolderAwareRequestFilter (8/11)
o.s.security.web.FilterChainProxy        : Invoking AnonymousAuthenticationFilter (9/11)
o.s.security.web.FilterChainProxy        : Invoking ExceptionTranslationFilter (10/11)
o.s.security.web.FilterChainProxy        : Invoking FilterSecurityInterceptor (11/11)
HttpSessionSecurityContextRepository : No HttpSession currently exists
SupplierDeferredSecurityContext : Created SecurityContextImpl [Null authentication]
SupplierDeferredSecurityContext : Created SecurityContextImpl [Null authentication]
o.s.s.w.a.AnonymousAuthenticationFilter  : Set SecurityContextHolder to AnonymousAuthenticationToken [Principal=anonymousUser, Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=<some_IP>, SessionId=null], Granted Authorities=[ROLE_ANONYMOUS]]
o.s.s.w.a.i.FilterSecurityInterceptor    : Did not re-authenticate AnonymousAuthenticationToken [Principal=anonymousUser, Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=<some_IP>, SessionId=null], Granted Authorities=[ROLE_ANONYMOUS]] before authorizing
o.s.s.w.a.i.FilterSecurityInterceptor    : Authorizing filter invocation [GET /<my_endpoint>/?<param1>=<value1>&<param2>=<value2>] with attributes [permitAll]
o.s.s.w.a.i.FilterSecurityInterceptor    : Authorized filter invocation [GET /<my_endpoint>/?<param1>=<value1>&<param2>=<value2>] with attributes [permitAll]
o.s.s.w.a.i.FilterSecurityInterceptor    : Did not switch RunAs authentication since RunAsManager returned null
o.s.security.web.FilterChainProxy        : Secured GET /<my_endpoint>/?<param1>=<value1>&<param2>=<value2>
WebApiLoggingFilter  : Server request: method=GET uri=/<my_endpoint>/?<param1>=<value1>&<param2>=<value2>
o.s.web.servlet.DispatcherServlet        : GET "<my_endpoint>/?<param1>=<value1>&<param2>=<value2>", parameters={<param1>:<value1>, <param2>:<value2>}, headers={authorization:[Bearer <bearer_token>], user-agent:[PostmanRuntime/7.43.0], accept:[*/*], cache-control:[no-cache], postman-token:[<some_token>], accept-encoding:[gzip, deflate, br],]} in DispatcherServlet 'dispatcherServlet'
.RequestMappingHandlerMapping : Mapped to az.supplychain.order.fulfillment.controller.WaveV1Controller#getWaves(String, boolean, LocalDate, LocalDate, Integer, Integer)
horizationManagerBeforeMethodInterceptor : Authorizing method invocation ReflectiveMethodInvocation: public org.springframework.http.ResponseEntity <my_controller>.<my_method>(<args>); target is of class [<my_controller>]
horizationManagerBeforeMethodInterceptor : Failed to authorize ReflectiveMethodInvocation: public org.springframework.http.ResponseEntity <my_controller>.<my_method>(<args>); target is of class [<my_controller>] with authorization manager org.springframework.security.config.annotation.method.configuration.DeferringObservationAuthorizationManager and decision ExpressionAuthorizationDecision [granted=false, expressionAttribute=hasAuthority('SCOPE_'+(@environment.getProperty('<the_required_scope>') ?: 'default').toLowerCase())]
.ExceptionHandlerExceptionResolver : Using @ExceptionHandler <my_controller_advice>.ServiceExceptionHandler#handleUnexpectedException(Exception)
o.s.web.method.HandlerMethod             : Arguments: [org.springframework.security.access.AccessDeniedException: Access Denied]
ServiceExceptionHandler      : Unexpected error
org.springframework.security.access.AccessDeniedException: Access Denied
spring-boot google-cloud-platform spring-security google-kubernetes-engine
1个回答
0
投票

我认为您遇到了 cors 问题,请尝试将其添加到您的默认过滤器链中

        .cors(Customizer.withDefaults())
© www.soinside.com 2019 - 2024. All rights reserved.