Spring安全oauth2登录/ Spring云网关发送302与XHR



我正在开发一个SPA应用程序(angular), BFF使用spring云网关配置为带有spring安全性的oauth2客户端,并将keycloak服务器作为授权服务器。我做了一个spring安全的经典配置:

@Configuration
@EnableWebFluxSecurity
public class SecurityConfiguration {
@Bean
public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
http.authorizeExchange(exchanges -> exchanges.anyExchange().authenticated())
.oauth2Login(withDefaults())
.csrf().disable()
;
return http.build();
}
}

网关配置TokenRelay作为默认过滤器。

我得到的问题是,当我发出XHR请求时,主要调用API,如果没有会话存在或已过期,网关将响应重定向到登录页面。当使用浏览器发出请求但不使用ajax请求时,这很好,因为我无法区分302,因为我没有从常规302进行身份验证。

我知道这是spring安全性的预期行为(参见https://github.com/spring-projects/spring-security/issues/9266)。但是,如何更改此行为,为未经过身份验证的XHR至少发送401呢?

谢谢!

我的原始答案与参考基于Javascript的web应用程序(或移动应用程序)配置为"公共"OAuth2客户端和对安全透明的spring-cloud-gateway违背了最新的建议。下面是一个从下游资源服务器返回状态码的解决方案,后面的网关配置为带有TokenRelay过滤器的OAuth2客户端(就像在问题中明智地做的那样)。

网关后面的REST api应该配置为资源服务器,并实现它们自己的访问控制,在这种情况下,它将为未授权的请求返回401,以保护资源。

在这种情况下,只需网关上的permitAll():

  • 如果用户会话被授权,则TokenRelay在转发请求前设置Authorization报头,资源服务器应以2xx
  • 响应。
  • 如果用户会话没有被授权,那么TokenRelay在转发请求之前不会设置Authorization头,资源服务器应该用401
  • 回应

我有一个系统的工作示例,其中有一个Angular前端,一个Spring REST API配置为无状态资源服务器和一个BFF (spring-cloud-gatewayspring-boot-starter-oauth2-client,oauth2LoginTokenRelay=过滤器)。代码源代码在本教程中。

在这个应用中,重定向到login不会发生,因为对受保护资源的未授权请求:Angular应用会显式触发这种重定向。所有配置了TokenRelay过滤器的路由都配置了permitAll()

最新更新