gpt4 book ai didi

spring - 当我在授权 header 中发送我的有效承载 token 时,为什么我没有通过我的 Spring-Cloud Gateway/OAuth2-Client 进行身份验证?

转载 作者:行者123 更新时间:2023-12-04 11:26:15 29 4
gpt4 key购买 nike

我正在开发一个微服务基础设施,并首先实现一个 Spring Cloud Gateway 来代理我的所有请求。我通过 spring-boot-starter-oauth2-client Dependency 使用 keycloak 保护了我的网关。
我使用 TokenRelay 过滤器将承载附加到我的代理请求。
我基本都在关注这个博客 https://blog.jdriven.com/2019/11/spring-cloud-gateway-with-openid-connect-and-token-relay/

spring.security.oauth2.client.provider.keycloak.issuer-uri=http://localhost:8090/auth/realms/testrealm
spring.security.oauth2.client.provider.keycloak.user-name-attribute=preferred_username
spring.security.oauth2.client.registration.keycloak.client-id=yyy
spring.security.oauth2.client.registration.keycloak.client-secret=xxx
spring.cloud.gateway.default-filters[0]=TokenRelay
现在我正在路由任何匹配/ping 到我的 Ping 微服务的请求。
spring.cloud.gateway.routes[0].id=some-id
spring.cloud.gateway.routes[0].uri=http://localhost:8079
spring.cloud.gateway.routes[0].predicates[0]=Path=/ping
Ping 微服务是一个 spring-boot-starter-oauth2-resource-server,并如此配置,并且只暴露一个测试端点/ping。
spring.security.oauth2.resourceserver.jwt.issuer-uri=http://localhost:8090/auth/realms/testrealm

@Configuration
@EnableWebSecurity
@RestController
public class SecurityConfig extends KeyCloakSecurityConfig {
@GetMapping("/ping")
public String ping() {
return "hello";
}
// ... resource server configuration in KeyCloakSecurityConfig
}

现在我访问我的网关(在 8765 上运行),通过 http://localhost:8765/ping 我被正确重定向到 keycloak 的登录页面。我使用我的 testuser 登录,并被重定向到我的网关,然后将我的请求代理到 Ping 微服务。 PingMicroService 再次针对 Keycloak 验证 AccessToken,我收到了“你好”。
但是,如果我想用 Postman 等测试我的 API,我会假设,我可以在调用我的/ping 端点之前将 Bearer-Token 添加到 Authorization Header 中。
因此,我使用 token 端点 http://localhost:8090/auth/realms/testrealm/protocol/openid-connect/token 获取我的 Accesstoken,并将其复制到我的网关请求的授权 header 中。
但是发送后,我得到了登录页面,而不是请求的资源。
enter image description here
当我在授权 header 中发送我的有效承载 token 时,为什么我的网关没有通过身份验证?
当我直接调用我的资源服务器时,承载 token 被接受。这是有道理的,因为 api 网关除了将我的访问 token 中继到资源服务器之外没有做任何其他事情,因此他可以进行必要的 token 自省(introspection)。
经过一些研究,我发现当我通过浏览器进行 api 调用时,Spring 实际上向我发送了一个 SESSION 作为 cookie。
当我将此 SESSION 作为 cookie 复制到 postman 的请求中时,一切正常。
是否有一些关于为什么 Spring 使用 SESSION 的文档,或者这基本上是 Auth-Code,因为我们在这里使用授权代码流?
更新:
经过一番研究,我发现我的网关确实已经是无状态的,因此 sessioncookie 不是来自我的网关,而是来自 oauth2-client 依赖项(请参阅 How to make API Gateway Stateless for Authentication/Authorization Process Using Oauth2? )。
所以我用一个简单的 Spring Boot 应用程序重现了我的问题,使用 keycloak 设置 OAuth2login 并公开一个端点/ping。
https://github.com/smotastic/spring-oauth2-client-keycloak
如果您使用有效的 Bearer Access-Token 调用/ping,应用程序会将您重定向到 keycloak 的登录页面,而不接受该 token ,因为它需要一个有效的 SESSION-Cookie

最佳答案

所以对于任何有类似问题的人。
问题出在 spring-boot-starter-oauth2-client 依赖项中。
这使我的网关有状态,通过从授权服务器发回 SESSION-Cookie 而不是 Access-Token。
不幸的是,我无法使用 Keycloak ( https://www.keycloak.org/docs/latest/securing_apps/#_spring_boot_adapter ) 提供的官方 Spring-Boot-Adapter,因为该适配器具有一些 Web 依赖项,并且由于 spring-cloud-gateway 是基于 webflux 构建的,因此 keycloak 所需的 Web 依赖项不能结合使用。
我的解决方案 是,不再使用 spring-cloud-gateway,而是使用 spring-cloud-starter-netflix-zuul 网关 .
这是建立在网络上的,而不是建立在 webflux 上的,所以我可以通过 keycloak 使用官方的 Spring-Boot-Adapter。

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-spring-boot-starter</artifactId>
</dependency>
Zuul 也发送一个 JSessionId,但仍然接受请求头中的 accesstoken(如果设置)作为有效授权。
请注意,Zuul 被置于维护模式 ( https://cloud.spring.io/spring-cloud-netflix/multi/multi__modules_in_maintenance_mode.html )。
所以它不会收到任何新功能,建议使用 spring-cloud-gateway 代替。
但是对于我的用例来说,这是不可行的,所以我将来可能会回到这个网关,如果 oauth2-client 发布更新,我也可以在那里进行无状态身份验证。
这是一个示例存储库,它使用 zuul-gateway,由使用官方 Spring-Boot-Keycloak-Adapter 的 keycloak 保护
https://github.com/smo-snippets/spring-cloud-microservices/tree/master/api-gateway

关于spring - 当我在授权 header 中发送我的有效承载 token 时,为什么我没有通过我的 Spring-Cloud Gateway/OAuth2-Client 进行身份验证?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65904945/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com