【问题标题】:Rest call requires JSESSIONID (Spring boot, Spring Security, OAuth2, Zuul)Rest 调用需要 JSESSIONID(Spring boot、Spring Security、OAuth2、Zuul)
【发布时间】:2016-10-06 19:49:42
【问题描述】:

我有两个 spring-boot 进程。我在两者上都启用了 Spring Security,并且我正在使用 Spring Security OAuth2 SSO 设置。我还使用 Eureka 和 Zuul 来允许调用 Boot1 来调用 Boot2 中的服务。 UI 使用 Angular 和 REST 调用服务,使用的令牌是 Json Web 令牌。

这一切似乎都有效,当然在 UI 中。所有请求都使用授权标头(包含 JWT)和服务中的 spring 安全过滤器成功解析 JWT 并从中提取安全上下文。作为 Spring Web 处理的一部分,它向客户端的 cookie 添加一个 JSESSIONID 值。

最近,我只在 Boot1 上安装了 Spring 安全性。当调用 REST 服务到 Boot1 时,最终使用 Zuul 将请求转发到 Boot2,我在 REST 客户端中只需要在 JWT 中包含 Authorization 标头,一切正常。

但是,我最近在 Boot2 中添加了 Spring Security(使用 @EnableResourceServer 注释),现在休息调用失败,除非我同时拥有 Authorization 标头和包含 JSESSIONID 值的 Cookie 标头。调用不会失败,但会返回空值。

我已经启用了 Spring Security 的日志记录,它在 Boot1 中验证了所有内容。它进入同一个 ZuulFilter。但在 Boot2 上没有任何活动。

Zuul 中是否有一些东西需要定义 JSESSIONID 值才能转发请求?还是在 Boot2 中,由于引入了 Spring Security 过滤器,它需要一个 JSESSIONID 标头值?

---更新---

我已通过 boot1。据我所知, OAuth2TokenRelayFilter 中的代码正在引发异常。具体来说,getAccessToken 方法正在调用 restTemplate.getAccessToken().getValue(第 90 行,版本 1.1.0-RELEASE),这会引发 UserRedirectRequiredException。

因此,虽然 TokenRelayFilter 有一个令牌,但它正在尝试刷新它。当它收到一个异常时,它会抛出一个 BadCredentialsException 而不是使用已经定义的。

--- 更新 2 ---

在 OAuth2RestOperationsConfiguration 中放置一个断点,在没有 JSESSIONID 的情况下进行休息调用总是最终会创建一个新的 DefaultOAuth2ClientContext,因为它正在尝试创建会话范围的 bean。使用 JSESSIONID,它使用持久的 DefaultOAuth2ClientContext,它将具有上下文。

那么,在构造 DefaultOAuth2ClientContext 时,是否可以查看请求是否包含令牌并使用它?还是这样的?我们正在尝试转向无状态服务,这似乎是实现这一目标的障碍。

【问题讨论】:

  • 您的 Angular UI 如何获取由您的 Oauth2 服务器发出的 JWT 令牌,以及在使用 Angularjs $http 时它如何呈现给 Boot2 应用程序?我提出了一个相关教程项目的问题。 github.com/spring-guides/tut-spring-security-and-angular-js/…
  • 我试图实现的 - UI 应用程序 - 一个 @EnableSSO 应用程序,一旦经过身份验证,就可以对 Boot[n] 应用程序进行 $http 调用,即 @EnableResourceServer - 使用 JWT 令牌进行身份验证。不使用 zuul 代理(一旦我处理了跨源)
  • 客户端 UI 在登录后调用 Spring 的 /user 端点以获取有关用户的详细信息。其中包括 JWT。对 Rest 端点的所有后续调用都将 JWT 作为 HTTP 标头“授权”的一部分传递。对我们来说,我们想使用 Zuul 代理,因为它减少了对我们应用程序的攻击向量。但是,既然我们在两个进程上都具有安全性,那么无论我们最终在 javascript 中调用哪个资源服务器,它都可以正常工作。
  • 所以您必须在从 /user 端点获取 JWT 令牌后立即将其保存为 Cookie 吗?我很困惑,因为提到的 github 项目中的“oauth2”示例项目似乎没有将 JWT 存储在客户端的任何位置,但仍然能够从受 jwt 保护的“资源”服务器获取数据。
  • 我们已将令牌存储在 cookie 中。我们还使用了本地存储。我们注意到,如果您在标头中使用 JSESSIONID,Spring Security 上下文将针对 JSESSION 进行跟踪,并且 JWT 上下文将作为其中的一部分。我们发现当我们针对我们的服务使用网络应用程序时。当我们从平板应用程序(或其他不在浏览器中运行的客户端)调用 REST 服务时,我们需要确保将令牌嵌入到标头中。

标签: spring-security spring-boot spring-cloud


【解决方案1】:

原来是系统不同部分使用的客户端 ID 值存在问题。

查看 OAuth2TokenRelayFilter,如果为资源服务器 (boot1) 定义的 client-id 与请求提供的令牌中包含的令牌的一部分定义的匹配,它会尝试刷新令牌。就我而言,这是真的:令牌是使用相同的客户端 ID 定义的。

这确实是不正确的。当我更新我的休息客户端以使用令牌,但在请求令牌时使用不同的客户端 ID 时,请求会按预期正确转发,而不需要 jsessionid。这正是我想要的。

我怀疑这最终是由我的系统组件错误使用客户端 ID 值引起的。

【讨论】:

    猜你喜欢
    • 2017-09-11
    • 2017-02-12
    • 2019-01-03
    • 2017-08-01
    • 2021-06-22
    • 1970-01-01
    • 2018-05-07
    • 2019-06-25
    • 2015-04-01
    相关资源
    最近更新 更多