Spring Cloud Gateway 错误 403:禁止

问题描述 投票:0回答:2

背景

我正在创建一个基于微服务的项目。我使用

Angular 15
表示前端,使用
Spring 3.0.2
表示后端。我使用
Keycloack 20.0.3
进行前端和后端的身份验证。我有多个微服务在不同的 Spring 项目上运行。我使用
Spring Cloud Gateway
作为前端的入口点,因此我不需要使用 Angular 管理端口。我还使用
Eureka
作为我的网关。

注意:我的网关仅配置有 YAML 文件。它既未配置

Spring Security
也未配置
Keycloak
。 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 API,Keycloak Auth 处理所有登录/注销/注册...

我失败的解决方案

我的网关未配置

Spring Security
Keycloak
。 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

需要钥匙斗篷

Spring Web
导致与
Spring Cloud Gateway

发生冲突

我花了两周时间,在互联网上找不到任何东西。一切要么被贬低,要么根本不起作用。有什么线索吗?

注意:我知道我可以使用 Angular 代理配置来替换网关,但这会破坏 Spring 云架构,并且只是用于开发目的的解决方法

angular spring spring-security keycloak spring-cloud-gateway
2个回答
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 过滤器

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();
    }
}

1
投票

我不会回答您当前的问题,但会尝试为您提供后续步骤的要素:我想最终,您希望您的应用程序得到保护(实现某种基于用户的访问控制),并且当您提到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 上写了 
教程

© www.soinside.com 2019 - 2024. All rights reserved.