尝试在 Spring MVC 中使用 OAuth 保护资源

2024-05-04

我们已经在 Spring MVC 上使用 Java 编写了 REST Web 服务,我一直在努力保护它们。

OAuth 服务器在另一个网站中实现,该网站处理登录和访问令牌的创建。因此,在允许用户访问网络服务之前,我需要验证访问令牌是否正确。

然而,带有 OAuth 的 Spring Security 的文档似乎非常糟糕,并且示例代码实际上并没有解释它在做什么!我什至不确定我是否应该为此实现它,因为它应该是一个如此简单的检查。

保护这些 Web 服务的最佳方法是什么?最好的开始方式是什么?

谢谢你的帮助。


重要的

[Edit 12/27/2012: The tutorial I reference below is now throwing a 404. There is a slightly updated version of this tutorial on github. I've struck through the links which appear to be bad. For now I'm leaving this as-is for posterity since the now-missing tutorial is the one referenced by the asker. To the best of my knowledge, the information contained herein is still useful, so maybe someday when I have time I'll rewrite it against the new tutorial.]

此答案假设“OAuth 服务器是在另一个网站中实现的,该网站处理登录和访问令牌的创建”。您的意思是您正在不属于您自己的单独站点上使用服务。

背景

我当然可以理解你的文档问题。 Spring Security 可以说是所有 Spring 项目中学习曲线最陡的,而且 OAuth 支持相当新,并且与 Spring Security 分开维护。 Spring Security OAuth 文档are sparse.

如果您对 OAuth 没有很好的感觉,那就去买一个吧!您要求您的用户相信您的网站实施此标准的安全性。因此,您对这个主题的理解不能有任何歧义!明显的起点是OAuth.net http://oauth.net/OAuth 初学者指南 http://hueniverse.com/oauth/在 huniverse。

如果/一旦您对 OAuth 的工作原理有了很好的了解,我强烈建议您阅读 Spring Security ”入门 http://static.springsource.org/spring-security/site/start-here.html" and "文章和教程 http://static.springsource.org/spring-security/site/articles.html” 文档列表可以让您更好地了解 Spring Security 的总体实现方式。

Once you have a decent knowledge of Spring Security and a decent knowledge of OAuth, the official Spring Security OAuth user guide http://static.springsource.org/spring-security/oauth/userguide.html will start to make sense. You'll want to pay attention particularly the Consumer/Client sections for the version of OAuth you're working with (1.0 http://static.springsource.org/spring-security/oauth/oauth1.html#OAuth_1.0_Consumer or 2.0 http://static.springsource.org/spring-security/oauth/oauth2.html#OAuth_2.0_Client).

That same site also has a decent tutorial http://static.springsource.org/spring-security/oauth/tutorial.html for both OAuth 1.0 and OAuth 2.0 which is based on the second section of the services OAuth Beginner's Guide http://hueniverse.com/oauth/ mentioned above.

访问受保护的 Restful 资源

For your problem we're going to focus on the implementation of the Tonr photo printing service from the tutorial http://static.springsource.org/spring-security/oauth/tutorial.html mentioned above. This service prints photos which are OAuth protected resources hosted by external sites. Tonr defers to these sites for access control of these resources. This will include redirecting the user for user authentication and authentication confirmation if necessary.

Spring-MVC REST services/controllers which are themselves consumers of external OAuth protected resources implement this "deferred authorization" (my term) behavior through the use of request filters. Per the 1.0 user guide http://static.springsource.org/spring-security/oauth/oauth1.html#OAuth_1.0_Consumer_Request_Filters:

有两个请求过滤器,分别是 适用于 OAuth 消费者 逻辑。第一个过滤器,OAuthConsumer 上下文过滤器 http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth/consumer/OAuthConsumerContextFilter.html, 是 负责建立一个 OAuth 特定的安全上下文,非常 类似于 Spring Security 的安全上下文 http://static.springsource.org/spring-security/oauth/oauth1.html#SecurityContext。安全环境 仅包含一组访问令牌 已获得的 当前用户。这个安全上下文是 提出请求时利用 受保护的资源。

还有另一个请求过滤器,OAuth消费者处理过滤器 http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth/consumer/OAuthConsumerProcessingFilter.html, 那 可以应用于特定的 URL 或 URL 需要访问的模式 远程受保护资源。推杆 Spring Security 中的这个过滤器 过滤器链将确保任何 指定所需的访问令牌 之前会获取 URL 模式 允许访问资源。

正如您所看到的,对于 OAuth 1.0,使用有效的过滤请求OAuthConsumerProcessingFilter将处理与获取有效访问令牌相关的所有事务,以及在访问被拒绝时通知用户。同样有相应的OAuth2ClientContextFilter http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth2/consumer/OAuth2ClientContextFilter.html and OAuth2ClientProcessingFilter http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth2/consumer/OAuth2ClientProcessingFilter.html类。

最后,完成所有设置后,您可以使用以下命令访问控制器中受 OAuth 保护的资源OAuthRestTemplate or OAuth2RestTemplate就像您使用正常方式访问不受保护的资源一样RestTemplate (info here http://blog.springsource.com/2009/03/27/rest-in-spring-3-resttemplate/)。但是,它们必须通过实例注入到您的服务或控制器中受保护资源详细信息 http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth/consumer/ProtectedResourceDetails.html or OAuth2ProtectedResource详细信息 http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth2/consumer/OAuth2ProtectedResourceDetails.html.

如果这听起来很复杂,我有个好消息。所有这些废话通常都会被 OAuth 和 OAuth2 XML 命名空间抽象并为您处理

oauth 命名空间在 Tonr 教程的 XML 配置文件中进行了演示,该文件位于各自的 src/webapp/WEB-INF 目录中。下面的例子是直接从那里缩写的。

如果您想了解提供商方如何工作without使用 OAuth 命名空间,我建议您检查这个 SpringSource 论坛帖子 http://forum.springsource.org/showthread.php?105656-non-namespace-configuration,并关注问题SECOAUTH-53 https://jira.springsource.org/browse/SECOAUTH-53用于更新。

OAuth 1.0 示例

Tonr 正在使用来自 Sparklr 和 Google 的受 OAuth 保护的服务,因此它设置了一个ProtectedResourceDetailsService called resourceDetails使用oauth:resource-details-service标签。然后它设置OAuthConsumerContextFilter and OAuthConsumerProcessingFilter并参考resourceDetails通过使用oauth:consumer标签。这些过滤器是使用以下实例创建的ProtectedResourceDetails对于每个受保护的资源提供者,使用oauth:resource tag.


来自tonr的applicationContext.xml:

<oauth:consumer resource-details-service-ref="resourceDetails" oauth-failure-page="/oauth_error.jsp">
  <oauth:url pattern="/sparklr/**" resources="sparklrPhotos"/>
  <oauth:url pattern="/google/**" resources="google"/>
</oauth:consumer>

<oauth:resource-details-service id="resourceDetails">
  <oauth:resource id="sparklrPhotos"
                  key="tonr-consumer-key"
                  secret="SHHHHH!!!!!!!!!!"
                  request-token-url="http://localhost:8080/sparklr/oauth/request_token"
                  user-authorization-url="http://localhost:8080/sparklr/oauth/confirm_access"
                  access-token-url="http://localhost:8080/sparklr/oauth/access_token"/>
  <!--see http://code.google.com/apis/accounts/docs/OAuth_ref.html-->
  <oauth:resource id="google" key="anonymous" secret="anonymous"
                  request-token-url="https://www.google.com/accounts/OAuthGetRequestToken"
                  user-authorization-url="https://www.google.com/accounts/OAuthAuthorizeToken"
                  access-token-url="https://www.google.com/accounts/OAuthGetAccessToken"
                  request-token-method="GET"
                  access-token-method="GET">
    <oauth:addtionalParameter name="scope" value="https://picasaweb.google.com/data/"/>
    <oauth:addtionalParameter name="xoauth_displayname" value="Tonr Example Application"/>
  </oauth:resource>
</oauth:resource-details-service>


接下来是sparklrService and googleServicebeans被创建,每个都有自己的内部OAuthRestTemplatebean,每个 bean 都通过提供参考constructor-arg到各自的ProtectedResourceDetails之前创建并注入到ProtectedResourceDetailsService bean.


来自tonr的spring-servlet.xml:

<bean id="sparklrService" class="org.springframework.security.oauth.examples.tonr.impl.SparklrServiceImpl">
  <property name="sparklrPhotoListURL" value="${sparklrPhotoListURL}"/>
  <property name="sparklrPhotoURLPattern" value="${sparklrPhotoURLPattern}"/>
  <property name="sparklrRestTemplate">
    <bean class="org.springframework.security.oauth.consumer.OAuthRestTemplate">
      <constructor-arg ref="sparklrPhotos"/>
    </bean>
  </property>

</bean>
<bean id="googleService" class="org.springframework.security.oauth.examples.tonr.impl.GoogleServiceImpl">
  <property name="googleRestTemplate">
    <bean class="org.springframework.security.oauth.consumer.OAuthRestTemplate">
      <constructor-arg ref="google"/>
    </bean>
  </property>

</bean>

OAuth 2.0 示例

我在这里的理解有点薄弱。部分原因是 OAuth2 命名空间似乎抽象了很多。此外,Tonr 2 示例似乎还没有像原始 Tonr 示例那样充实。我会尽力并在必要时进行编辑。

首先一个oauth:client标签被创建并给出对InMemoryOAuth2ClientTokenServices豆。看来这设置了适当的过滤器。然后OAuth2ProtectedResourceDetailsbeans 是为sparklr 和Facebook 创建的oauth:resource.


来自tonr 2的applicationContext.xml:

<!--apply the oauth client context-->
<oauth:client token-services-ref="oauth2TokenServices"/>

<beans:bean id="oauth2TokenServices" class="org.springframework.security.oauth2.consumer.token.InMemoryOAuth2ClientTokenServices"/>

<!--define an oauth 2 resource for sparklr-->
<oauth:resource id="sparklr" type="authorization_code" clientId="tonr"
                  accessTokenUri="http://localhost:8080/sparklr/oauth/authorize"
                  userAuthorizationUri="http://localhost:8080/sparklr/oauth/user/authorize"/>

<!--define an oauth 2 resource for facebook. according to the facebook docs, the 'clientId' is the App ID, and the 'clientSecret' is the App Secret -->
<oauth:resource id="facebook" type="authorization_code" clientId="162646850439461" clientSecret="560ad91d992d60298ae6c7f717c8fc93"
                  bearerTokenMethod="query" accessTokenUri="https://graph.facebook.com/oauth/access_token"
                  userAuthorizationUri="https://www.facebook.com/dialog/oauth"/>


接下来,就像前面的示例一样,每个需要访问受保护资源的控制器或服务 bean 都是使用内部创建的OAuth2RestTemplate豆。这个内部 bean 被赋予了正确的引用OAuth2ProtectedResourceDetails豆通过constructor-arg.


来自tonr 2的spring-servlet.xml:

<bean id="facebookController" class="org.springframework.security.oauth.examples.tonr.mvc.FacebookController">
  <!-- snipped irrelevant properties -->
  <property name="facebookRestTemplate">
    <bean class="org.springframework.security.oauth2.consumer.OAuth2RestTemplate">
      <constructor-arg ref="facebook"/>
    </bean>
  </property>
  <property name="tokenServices" ref="oauth2TokenServices"/>
</bean>

<bean id="sparklrService" class="org.springframework.security.oauth.examples.tonr.impl.SparklrServiceImpl">
  <!-- snipped irrelevant properties -->
  <property name="sparklrRestTemplate">
    <bean class="org.springframework.security.oauth2.consumer.OAuth2RestTemplate">
      <constructor-arg ref="sparklr"/>
    </bean>
  </property>
  <property name="tokenServices" ref="oauth2TokenServices"/>
</bean>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

尝试在 Spring MVC 中使用 OAuth 保护资源 的相关文章

随机推荐