我使用spring Boot 3.0.2和spring cloud gateway。此外,我使用spring- Boot -starter-oauth2-resource-server在Keycloak服务器上获取和检查jwt token以确保安全。我的build.gradle文件如下:
plugins {
id 'java'
id 'org.springframework.boot' version '3.0.2'
id 'io.spring.dependency-management' version '1.1.3'
}
dependencies {
implementation 'org.springframework.cloud:spring-cloud-starter'
implementation 'org.springframework.boot:spring-boot-starter-webflux'
implementation 'org.springframework.cloud:spring-cloud-starter-gateway'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-data-mongodb'
implementation 'org.springframework.boot:spring-boot-starter-oauth2-resource-server'
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'com.shahrtech.service.libs:service-common-libs:0.0.61'
implementation 'org.springframework.cloud:spring-cloud-starter-circuitbreaker-reactor-resilience4j'
implementation 'org.springframework.cloud:spring-cloud-starter-loadbalancer'
}
字符串
而application.yml上的配置文件是:
spring :
cloud:
gateway:
default-filters:
- DedupeResponseHeader=Access-Control-Allow-Credentials Access-Control-Allow- Origin
globalcors:
corsConfigurations:
'[/**]':
allowedOrigins: "*"
allowedMethods: "*"
allowedHeaders: "*"
routes:
- id: auth-service
uri: http://x.x.x.x:8085/
predicates:
- Path=/auth-service/v1.0/**
filters:
- RewritePath=/auth-service/v1.0/(?<path>.*),/auth-service/v1.0/$\{path}
- RequestHashing=SHA-256
- id: customer-service
uri: http://x.x.x.x:8090/
predicates:
- Path=/customer-service/v1.0/**
filters:
- RewritePath=/customer-service/v1.0/(?<path>.*),/customer-service/v1.0/$\{path}
- RequestHashing=SHA-256
- TokenRelay=
security:
oauth2:
client:
registration:
keycloak:
client-id: login-app
authorization-grant-type: authorization_code
scope: openid
provider:
keycloak:
issuer-uri: http://x.x.x.x:9002/auth/realms/app
user-name-attribute: preferred_username
resourceserver:
jwt:
issuer-uri: http://x.x.x.x:9002/auth/realms/app
型
ApiGatewayServiceApplication.java是:
@SpringBootApplication
@EnableDiscoveryClient
@EnableWebFluxSecurity
@EnableReactiveMethodSecurity
public class ApiGatewayServiceApplication {
@Bean
public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
http.cors().and().csrf()
.csrfTokenRepository(CookieServerCsrfTokenRepository.withHttpOnlyFalse())
.and()
.authorizeExchange()
.anyExchange().authenticated()
.and()
.oauth2ResourceServer()
.jwt();
return http.build();
}
@Bean
CorsConfigurationSource corsConfiguration() {
CorsConfiguration corsConfig = new CorsConfiguration();
corsConfig.applyPermitDefaultValues();
corsConfig.addAllowedMethod(HttpMethod.PUT);
corsConfig.addAllowedMethod(HttpMethod.DELETE);
corsConfig.setAllowedOrigins(Arrays.asList("*", "**"));
corsConfig.setAllowCredentials(true);
UrlBasedCorsConfigurationSource source =
new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", corsConfig);
return source;
}
public static void main(String[] args) {
SpringApplication.run(ApiGatewayServiceApplication.class, args);
}
型
}
我也使用这个Bean来更改安全配置:
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.requestMatchers(new AntPathRequestMatcher("/auth-service/**")).permitAll()
.anyRequest().permitAll()
.and()
.httpBasic()
.and()
.csrf().disable()
.cors().disable();
return http.build();
}
型
一切都很好。当在Postman中使用头部中的token调用API时,一切都很好。但是我们试图开发一个示例JS和ReactJs代码来获得API,我们收到错误401和控制台日志,并跟踪它显示请求头部授权未被接受。我们研究并找到这篇文章:Spring Gateway and Auth0: IllegalArgumentException: Unable to find GatewayFilterFactory with name TokenRelay,它说在配置中添加TokenRelay。我在配置中添加了TokenRelay,并重试,但错误存在。
一切都很好。当在Postman中使用头部中的token调用API时,一切都很好。但是我们试图开发一个示例JS和ReactJs代码来获得API,我们收到错误401和控制台日志,并跟踪它显示请求头部授权未被接受。我们研究并找到这篇文章:Spring Gateway and Auth0: IllegalArgumentException: Unable to find GatewayFilterFactory with name TokenRelay,它说在配置中添加TokenRelay。我在配置中添加了TokenRelay,并重试,但错误存在。
2条答案
按热度按时间c86crjj01#
TokenRelay
过滤器将session cookie替换为session中的访问令牌。要在session中拥有此访问令牌,它当然需要sessions,但也需要oauth2Login()
(带有authorization_code
注册的Spring OAuth2客户端实现)。不要将
oauth2Login()
和oauth2ResourceServer()
混合在一个SecurityFilterChain
中,安全需求太不相同:authorization_code
的客户端会话401 Unauthorized
(缺少令牌或令牌无效)302 Redirect to login
(会话尚未包含授权客户端)根据最新的建议,我们应该避免使用“公共”OAuth2客户端,在浏览器或移动的应用程序中运行的任何东西都只能是“公共”OAuth2客户端=>浏览器中的代码(纯JavaScript或SPA框架)不应该从授权服务器获取令牌。
你也许应该:
oauth2Login()
和TokenRelay
过滤器配置网关(最小依赖项为spring-boot-starter-oauth2-client
和spring-cloud-gateway
)oauth2ResourceServer()
配置下游REST API(最小依赖为spring-boot-starter-oauth2-resource-server
和spring-boot-starter-web
或spring-boot-starter-webflux
)从浏览器到网关的请求将使用会话cookie进行授权(并且应防止CSRF攻击)。
从Gateway(或Postman)到REST API的请求将使用访问令牌进行授权。
附注
在具有服务器端渲染部分的框架的情况下,例如next.js提供的,可以在该服务器端部分中使用实现OAuth2客户端的库:该服务器端库可以实现关于OAuth2和请求授权的相同重要功能:
spring-cloud-gateway
上的TokenRelay
一样)xienkqul2#
TokenRelay filter有一个bug,在spring-cloud-gateway https://github.com/spring-cloud/spring-cloud-gateway/releases/tag/v4.1.1的4.1.1版本中得到修复