我正在创建一个基于微服务的项目。我使用
Angular 15
表示前端,使用 Spring 3.0.2
表示后端。我使用 Keycloack 20.0.3
进行前端和后端的身份验证。我有多个微服务在不同的 Spring 项目上运行。我使用 Spring Cloud Gateway
作为前端的入口点,因此我不需要使用 Angular 管理端口。我还使用 Eureka
作为我的网关。
注意:我的网关仅配置有 YAML 文件。它既未配置
也未配置Spring Security
。 CORS 已禁用。Keycloak
spring:
application:
name: gateway
cloud:
gateway:
globalcors:
corsConfigurations:
'[/**]':
allowedOrigins: "https://localhost:4200"
allowedMethods: "*"
allowedHeaders: "*"
routes:
- id: users
uri: lb://micro-service-1/api/users
predicates:
- Method=GET,POST,PUT,DELETE
- Path=/api/users/**
- id: assets
uri: lb://micro-service-2/api/assets
predicates:
- Method=GET,POST,PUT,DELETE
- Path=/api/assets/**
server:
port: 8100
eureka:
client:
registerWithEureka: true
serviceUrl:
defaultZone: http://localhost:8761/eureka
我正在构建一个 BREAD api(浏览、阅读、编辑、添加、删除)。浏览和阅读(一般为 Http GET 请求)工作正常,但其余部分会在
Angular
中抛出 403 错误。
注意:我尝试使用 Postman 进行测试,不知何故没有抛出任何错误
当我尝试跳过网关并直接与微服务通信时,一切正常,不会抛出任何错误
注意:我的后端仅是 RESTful API,Keycloak Auth 处理所有登录/注销/注册...
我的网关未配置
Spring Security
和 Keycloak
。 CORS 已禁用。
security.enable-csrf: false
没成功!
Spring Security
并在网关上禁用 CSRF <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.csrf().disable().cors().disable().httpBasic().disable()
.authorizeHttpRequests(auth -> auth.anyRequest().permitAll());
return http.build();
}
仍需要凭据且与
Keycloak
冲突
Keycloak
需要钥匙斗篷
Spring Web
导致与Spring Cloud Gateway
发生冲突
我花了两周时间,在互联网上找不到任何东西。一切要么被贬低,要么根本不起作用。有什么线索吗?
注意:我知道我可以使用 Angular 代理配置来替换网关,但这会破坏 Spring 云架构,并且只是用于开发目的的解决方法
在尝试了一些不同的配置之后,我最终完成了这个工作。
spring:
application:
name: gateway
cloud:
gateway:
globalcors:
corsConfigurations:
'[/**]':
allowedOrigins: "*"
allowedMethods: "*"
allowedHeaders: "*"
routes:
- id: users
uri: lb://micro-service-1
predicates:
- Path=/api/users/**
filters:
- RewritePath=/api/users/(?<segment>.*),/api/users/$\{segment}
- id: assets
uri: lb://micro-service-2
predicates:
- Path=/api/assets/**
filters:
- RewritePath=/api/assets/(?<segment>.*),/storage/$\{segment}
server:
port: 8100
eureka:
client:
registerWithEureka: true
serviceUrl:
defaultZone: http://localhost:8761/eureka
更改:在
中,我仅设置了基本 uri,从路由中删除了方法并添加了 RewritePath 过滤器uri
Gateway Projet 的 POM 中没有包含身份验证或安全库。只有Spring Cloud
在每个单独的微服务中,我添加了以下
SecurityConfig
类
@Configuration
@EnableWebSecurity
class SecurityConfig {
@Bean
protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
}
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeHttpRequests(auth -> auth.anyRequest().authenticated());
http.oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt);
return http.build();
}
}
我不会回答您当前的问题,但会尝试为您提供后续步骤的要素:我想最终,您希望您的应用程序得到保护(实现某种基于用户的访问控制),并且当您提到Keycloak就会涉及到OpenID。
Spring 的 Keycloak 适配器已于 2022 年初被弃用,并且与 Spring Boot 3 不兼容。即使在 servlet 应用程序中也不要使用它(并且,正如您已经发现的,
spring-cloud-gateway
是一个反应式应用程序,所以这是不使用它的两个充分理由)。
您是否知道现在不鼓励在公共客户端(浏览器应用程序不仅是 Angular,还包括 React、Vue 等)中存储 OAuth2 令牌?事实上,如果您检查任何主要的 Web 服务(Gmail、Facebook、Github 等),您将找不到任何 OAuth2 访问令牌,而只是一个常规会话(使用安全 Http-Only cookie 实现)。
您听说过 BFF(后端用于前端)模式吗?为了帮助您提出自己的想法,我非常喜欢我最喜欢的 Angular OpenID 客户端库作者的 这篇文章 (当您实现 BFF 时,这没有任何用处)。 如果您打算将网关配置为 BFF,则需要
spring-boot-starter-oauth2-client
,而不是
spring-boot-starter-security
。 我在 Baeldung 上写了教程