我正在开发一个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-gateway
与spring-boot-starter-oauth2-client
,oauth2Login
和TokenRelay=
过滤器)。代码源代码在本教程中。
在这个应用中,重定向到login不会发生,因为对受保护资源的未授权请求:Angular应用会显式触发这种重定向。所有配置了TokenRelay
过滤器的路由都配置了permitAll()
。