【问题标题】:How to inform Spring 3.0.5 that the user has authenticated via OAuth2如何通知 Spring 3.0.5 用户已通过 OAuth2 进行身份验证
【发布时间】:2015-07-27 15:49:55
【问题描述】:

Google 在 4 月底停止支持 OpenID,我们需要将应用的身份验证系统迁移到 OAuth2。阅读Google’s guide,可以直接发出 OAuth 请求并检索我们的应用程序所需的 Google 用户信息。

但是,我们的应用程序大量使用 Spring security 3.0.5,因此我们必须将 OAuth 与 Spring security 集成。在标准的 Web 应用场景中,一旦用户成功登录,Spring 会自动创建一个 Spring 安全上下文对象。许多 JSP 页面使用 Spring 安全标签来检查用户是否已登录,或者用户是否为管理员用户,并确定要显示的适当页面内容。 Spring security oauth 似乎是完成这项工作的理想框架。

在开发工作期间,我遇到了以下问题:

  1. 在用户批准访问 Google oauth 页面上的基本信息后,Google 会将用户重定向回我们的应用程序页面(在 Google 应用程序控制台中预先配置)。我找不到检索用户信息的“Spring”方式(尽管我可以使用 Google API 检索用户信息)。

  2. 当 Google 将用户重定向回我们的应用程序时,Spring security 需要知道用户已成功通过身份验证,以便它可以创建一个 SecurityContext 对象。但到目前为止,我还没有找到让 Spring 安全知道这一点的方法。

我可以成功运行 Spring Oauth2 演示应用程序 tonr2 (github.com/spring-projects/spring-security-oauth/tree/1.0.0.RELEASE/samples/oauth2/tonr)。该演示要求用户使用本地用户名/密码登录,然后单击“访问 facebook 朋友”后,用户被重定向到 facebook 站点,使用 oauth 身份验证登录 facebook,最后检索他们的朋友列表。但是,我们希望避免上述两个身份验证步骤。这是一个可以按照我们希望的方式运行的网站示例(减去本地登录框)——请参阅http://lucy.me/login/auth

这里是读取谷歌用户配置文件的代码:

@RequestMapping(value = "google", method = RequestMethod.GET)
public String google(Model model, HttpServletRequest request, HttpServletResponse response) throws Exception {
  log.debug("Google OAuth filter trigger!");
  String c = request.getParameter("code");

  if(c==null || "".equals(c)) {
     // trigger google oauth2
  }else{
     ResponseEntity<Object> forEntity = googleRestTemplate.getForEntity("https://www.googleapis.com/oauth2/v1/userinfo", Object.class);
  }
}

【问题讨论】:

  • 你需要 Spring Social。检查this,它对 Facebook 和 Twitter 进行了解释,但对于 Google 应该类似(使用 Spring Social Google)。

标签: spring spring-security oauth-2.0 spring-security-oauth2


【解决方案1】:

简短的回答:你不能!

没有用户信息通过网络传输 - 用户名和密码。因此您无法在 OAuth 客户端应用程序的 Spring 上下文中找到它。

当从 Google 重定向到您的应用程序时,如果用户身份验证成功,重定向将返回一个 stateKey 和一个授权代码,这将允许 Spring Security 请求访问令牌。获得访问令牌后,您可以代表该用户向服务器发出请求,而无需了解有关他的任何信息。这就是 OAuth 的美妙之处。

前面提到的状态键会将重定向绑定到应用程序中的上下文。

您有责任在 Spring OAuth 客户端应用程序中拥有一个用户上下文,该上下文将绑定到您将从服务器 (Google) 获得的访问令牌/刷新令牌。

当然,如果用户授予您这样做的权限,您可以查询 Google 并获取用户名,否则,OAauth 协议将不允许您收集有关该用户的任何信息。

这是使用授权授予的基本流程:https://www.rfc-editor.org/rfc/rfc6749#section-4.1

【讨论】:

  • 到目前为止我所做的是使用 oauth 客户端将用户重定向到 google oauth 页面,Google 返回 stateKey 和 authz 代码。如果我理解正确,我需要进行第二次调用以获取访问代码并手动创建 Spring 安全上下文(例如自动登录),然后提取谷歌用户信息?
  • 您不必发起第二次调用来获取访问令牌,也不必手动创建 Spring OAuth 上下文。这由 Spring OAuth 本身处理。
  • @nucatus:你能告诉我spring security如何从授权码中获取访问令牌,而我们不必手动进行吗?以及它将如何创建principal 并将其添加到当前的 spring 安全上下文中??
  • 查看OAuth2RestTemplate#acquireAccessToken(OAuth2ClientContext oauth2Context)方法。更具体地说,这是在 oauth 本地上下文中设置访问令牌的位置:oauth2Context.setAccessToken(accessToken)。 oauth 上下文是 princilap 的一个属性,如果有的话 DefaultOAuth2ClientContext 而不是一个主体本身。如果需要持久化访问令牌,则需要实现并连接一个ClientTokenServices bean。有一个开箱即用的 JDBC 实现,JdbcClientTokenServices
  • @nucatus 嗨,我看过 OAuth2RestTemplate。方法 acquireAccessToken 是受保护的,所以假设它根据需要被其他方法调用。我的代码(附加在上面)给了我一个 400 bad request 错误,有什么想法吗?
猜你喜欢
  • 1970-01-01
  • 2015-11-08
  • 1970-01-01
  • 1970-01-01
  • 2012-06-05
  • 1970-01-01
  • 2019-12-26
  • 2019-09-18
相关资源
最近更新 更多