我正在尝试使用
Okta
、Spring Cloud Gateway
和 Spring Security
实现基于 Oauth2 的身份验证。我想要实现的目标是我希望 Spring Cloud Gateway 的路由可供所有人使用,而无需任何身份验证。我知道 Spring Cloud Gateway 使用 WebFlux
。因此,只有我在配置 Spring Security。 我在 Spring Cloud Gateway 中有三个路由。
我希望这些
/auth/**
路线中的任何一个都应该可供所有人使用,因为我的用户在这里注册,所以我不能在那里进行身份验证。对于另外两个 /doctors/**
和 /patients/**
我想要身份验证和授权。在云网关中的SecurityConfig
中,我试图实现相同的目标。目前我已经做了这个配置:
package com.sb.projects.medica.gateway.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.web.server.SecurityWebFilterChain;
@Configuration
@EnableWebFluxSecurity
public class SecurityConfig {
@Bean
public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity httpSecurity) {
httpSecurity.authorizeExchange(exchanges -> {
exchanges.pathMatchers("/doctor/**", "/patient/**").authenticated();
exchanges.pathMatchers("/auth/**").permitAll();
}).oauth2Client().and().oauth2ResourceServer().jwt();
return httpSecurity.build();
}
}
但似乎不起作用。当我尝试击中
/auth/**
的任何路线时,我得到
找不到预期的 CSRF 令牌
我该如何解决这个错误。如何创建 csrf 令牌并将其发送到前端
您显然刚刚开始 CSRF 配置之旅。我建议您从Spring 文档开始。就像真的一样。在阅读本答案的其余部分之前请仔细阅读。
网关后面的 REST API 可能可以配置为“无状态”(servlet 中的
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
或反应式应用程序中的 http.securityContextRepository(NoOpServerSecurityContextRepository.getInstance())
),因此可以在其上禁用 CSRF 保护 (http.csrf().disable()
)。然后,您使用 OAuth2 授权配置 Postman 并直接查询 API(不通过网关)。
根据您的 React 前端配置为 OAuth2 公共客户端或网关配置为 Backend F或 Frontend(带有
TokenRelay
过滤器的 OAuth2 机密客户端),CSRF 保护的需求有很大不同:
TokenRelay
过滤器才能工作(保持 OAuth2 令牌与每个浏览器会话关联)。因此,必须启用 CSRF,并且由于您的应用程序是基于 Javascript 的,因此必须启用 Cookie 存储库(http.csrf().csrfTokenRepository(CookieServerCsrfTokenRepository.withHttpOnlyFalse());
在像 spring-cloud-gateway
这样的反应式应用程序上)。然后,您必须配置前端以将 CSRF 令牌(作为 cookie 接收)作为 X-XSRF-TOKEN
标头发送(如果您想通过网关发送请求而不是直接查询 API,则对 Postman 的要求相同)。我写了一个关于 Baeldung 的完整指南。