Spring Cloud网关错误403:禁止访问。

3

背景

我正在创建一个基于微服务的项目。前端使用 Angular 15,后端使用 Spring 3.0.2。认证方面,我使用了 Keycloack 20.0.3 来为前后端提供身份验证。我的多个微服务运行在不同的 Spring 项目中。我使用 Spring Cloud Gateway 作为前端的入口,这样就不需要在 Angular 中管理端口号。同时,我还使用了 Eureka 作为网关。

注意:我的网关仅使用 YAML 文件进行配置,没有使用 Spring SecurityKeycloak 进行配置。CORS 被禁用。

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 APIs,Keycloak Auth处理所有的登录/注销/注册...

我的失败解决方案

我的网关未配置Spring SecurityKeycloak,CORS已禁用。

1. 尝试在网关上禁用CSRF

security.enable-csrf: false

它没有起作用!

2. 尝试在网关上添加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 冲突

3. 尝试为网关配置 Keycloak

Keycloak 需要 Spring Web,导致与 Spring Cloud Gateway 冲突


我花了2周时间,在互联网上找不到任何有用的信息。一切都已经过时或根本无法使用。有什么线索吗?

注意:我知道可以使用 Angular Proxy Config 替换网关,但这会破坏 Spring Cloud 架构,并且只是开发目的的解决方法。


我也遇到了同样的问题,你解决了吗? - Rafi
1
@Rafi,是的!我发布了一个答案,希望能有所帮助。 - galalem
2个回答

1

我不会回答你当前的问题,但是会给你一些下一步需要注意的元素:我猜最终你想要你的应用程序更加安全(实现某种用户基础访问控制),并且正如你提到的Keycloak,它将涉及OpenID。

2022年初,Spring的Keycloak适配器就已经被弃用了 并且不兼容Spring Boot 3。不要使用它,即使在servlet应用程序中也不要使用(而且,正如你已经发现的那样,spring-cloud-gateway是一个反应灵敏型应用程序,所以这是两个不使用它的好理由)。

你知道吗?在公共客户端(浏览器应用程序不仅仅是Angular,还有React、Vue等)中存储OAuth2令牌现在是不鼓励的吗?事实上,如果你检查任何主要的网络服务(Gmail、Facebook、Github等),你看不到任何OAuth2访问令牌,只会看到一个常规的会话(使用Secured Http-Only cookies实现)。

你听说过BFF(前端的后端)模式吗?为了帮助您形成自己的想法,我很喜欢我的首选Angular中OpenID客户端库的作者的本文(在实现BFF时没有任何用处)。
如果您打算将网关配置为BFF,则需要spring-boot-starter-oauth2-client而不是spring-boot-starter-security。我写的这篇教程仍在进行中,但它可能会帮助您入门:https://github.com/ch4mpy/spring-addons/tree/master/samples/tutorials/bff

1

在尝试了不同的配置后,我最终找到了这个可行的方案。

网关

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中,我只设置了基本uri,从路由中删除了方法,并添加了RewritePath过滤器。
网关项目未在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();
    }
}

尝试更改securityConfig,但仍然收到403访问控制错误。 - Rafi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接