尝试在Spring MVC中使用OAuth保护资源 [英] Trying to protect resources with OAuth in Spring MVC
问题描述
我们已经在Spring MVC上使用Java编写了REST Web服务,我一直在尝试保护它们。
We already have REST web services written in Java on Spring MVC and I have been trying to protect them.
OAuth服务器在另一个处理登录和创建访问令牌。因此,我需要在授予用户访问Web服务的权限之前验证访问令牌是否正确。
The OAuth server is implemented in another website which handles the logging in and creation of the Access Token. I need therefore to verify that the access token is correct before giving the users access to the webservices.
但是,使用OAuth的Spring Security文档看起来确实很差,并且示例代码实际上并没有解释它在做什么!我甚至不确定我是否应该为此实现它,因为它应该是这么简单的检查。
However the documentation for Spring Security with OAuth seems to be really poor, and the example code doesn't actually explain what it is doing! I am not even sure if I should be implementing it for this, as it should be such a simple check.
保护这些Web服务的最佳方法是什么?什么是最好的入门方式?
What is the best way to go about protecting these web services? And what is the best way to get started?
感谢您的帮助。
推荐答案
重要
Important
这个答案假设OAuth服务器是在另一个处理登录和创建访问令牌的网站中实现的。您的意思是您在不属于您自己的单独网站上使用服务。
This answer assumes that by "The OAuth server is implemented in another website which handles the logging in and creation of the Access Token." You mean that you are consuming a service on a separate site that is not your own.
我当然可以解决你的文档问题。 Spring Security可以说是任何Spring项目中最陡峭的学习曲线,OAuth支持相当新,并且与Spring Security分开维护。 Spring Security OAuth文档 稀疏。
I can certainly relate to your documentation woes. Spring Security has arguably the steepest learning curve of any Spring project, and OAuth support is fairly new and maintained separately from Spring Security. The Spring Security OAuth docs are sparse.
如果你对OAuth没有好感,那就去买一个吧! / strong>您要求您的用户信任您网站实施此标准的安全性。因此,您无法理解您对该主题的理解!显而易见的起点是 OAuth.net 和 OAuth初学者指南。
如果/您对OAuth的工作方式有一个良好的感觉,我强烈推荐阅读Spring Security使用入门和文章和教程文档列表,以便更好地了解Spring Security的实现方式一般来说。
If/Once you have a good feel for how OAuth works, I'd highly recommend reading through the Spring Security "Getting Started" and "Articles and Tutorials" documentation lists to get a good feel for how Spring Security is implemented in general.
一旦你对Spring Security有了不错的了解并且对OAuth有了不错的了解,官方的Spring Security OAuth 用户指南 将开始有意义。您将特别关注正在使用的OAuth版本的消费者/客户端部分( 1.0 或 2.0 )。
Once you have a decent knowledge of Spring Security and a decent knowledge of OAuth, the official Spring Security OAuth user guide 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 or 2.0).
同一网站也有一个不错的 教程 基于第二部分上面提到的 OAuth初学者指南服务。
That same site also has a decent tutorial for both OAuth 1.0 and OAuth 2.0 which is based on the second section of the services OAuth Beginner's Guide mentioned above.
对于您的问题,我们将重点关注从 教程 。此服务打印的照片是由外部网站托管的受OAuth保护的资源。 Tonr推迟到这些站点访问这些资源。这将包括重定向用户以进行用户身份验证和身份验证确认(如果有必要)。
For your problem we're going to focus on the implementation of the Tonr photo printing service from the tutorial 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服务/控制器本身是外部OAuth受保护资源的消费者实现此延迟通过使用请求过滤器授权(我的术语)行为。根据1.0 用户指南 :
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:
有两个请求过滤器,
适用于OAuth使用者
逻辑。第一个过滤器,
OAuthConsumerContextFilter ,是
,负责建立
OAuth特定的安全上下文,非常类似于Spring Security的
。 springsource.org/spring-security/oauth/oauth1.html#SecurityContextrel =noreferrer> SecurityContext 。安全上下文
只包含一组为
当前用户获取的访问令牌
。在向
受保护资源发出请求时,此安全上下文是
。
There are two request filters that are applicable to the OAuth consumer logic. The first filter, OAuthConsumerContextFilter, is responsible for establishing an OAuth-specific security context, very similar to Spring Security's SecurityContext. The security context simply contains a set of access tokens that have been obtained for the current user. This security context is leveraged when making requests for protected resources.
还有另一个请求过滤器,
OAuthConsumerProcessingFilter ,
可以应用于需要访问
远程受保护资源的特定URL或URL
模式。在Spring Security的
过滤器链中放置
此过滤器将确保在允许访问资源的
之前获得指定的
URL模式所需的任何
访问令牌。
There is another request filter, OAuthConsumerProcessingFilter, that can be applied to specific URLs or URL patterns that require access to a remote protected resource. Putting this filter in Spring Security's filter chain will ensure that any access tokens needed for the specified URL patters will be obtained before allowing access to the resources.
正如您所看到的,对于OAuth 1.0,使用有效的 OAuthConsumerProcessingFilter $ c $过滤请求c>将处理获取有效访问令牌的所有内容,并在访问被拒绝时通知用户。同样有相应的
OAuth2ClientContextFilter
和 OAuth2ClientProcessingFilter
类。
So as you can see, for OAuth 1.0, filtering requests with a valid OAuthConsumerProcessingFilter
will handle everything surrounding acquiring valid Access Tokens, as well as notifying the user when access is denied. Likewise there is are corresponding OAuth2ClientContextFilter
and OAuth2ClientProcessingFilter
classes.
最后,一旦这是设置完成后,您可以使用 OAuthRestTemplate
或 OAuth2RestTemplate
访问控制器中受OAuth保护的资源,就像访问不受保护的资源一样正常 RestTemplate
(info 这里)。但是,它们必须通过 ProtectedResourceDetails 或 OAuth2ProtectedResourceDetails 。
Finally, once this is all set up you can access OAuth protected resources in your controllers with OAuthRestTemplate
or OAuth2RestTemplate
just like you would access unprotected resources with the normal RestTemplate
(info here). However they must be injected into your service or controller with an instance of ProtectedResourceDetails or OAuth2ProtectedResourceDetails.
如果这听起来很复杂,我有个好消息。所有这些废话通常都是抽象的,并由OAuth和OAuth2 XML命名空间为您处理
I have good news if this sounds complex. All of this nonsense is typically abstracted away and handled for you by the OAuth and OAuth2 XML Namespaces
oauth命名空间在位于其中的Tonr教程的XML配置文件中进行了演示。各自的src / webapp / WEB-INF目录。以下示例直接从那里缩写。
The oauth namespace is demonstrated in the Tonr tutorials' XML config files located in their respective src/webapp/WEB-INF directories. The examples below are abbreviated directly from there.
如果您想了解提供者方如何在没有使用OAuth名称空间的情况下工作,我'建议您查看此SpringSource论坛帖子,并按照问题进行操作 SECOAUTH-53 了解更新。
If you'd like to see how the provider side works without using OAuth namespaces, I'd suggest you check this SpringSource forum post, and follow the issue SECOAUTH-53 for updates.
此处Tonr正在使用Sparklr和Google的OAuth保护服务,因此设置了 ProtectedResourceDetailsService
使用 oauth:resource-details-service
标记调用 resourceDetails
。然后设置 OAuthConsumerContextFilter
和 OAuthConsumerProcessingFilter
,并引用 resourceDetails
使用 oauth:consumer
标记。使用 oauth:resource
标记为每个受保护资源提供程序创建了 ProtectedResourceDetails
的实例。
Tonr is consuming OAuth protected services from both Sparklr and Google here, so it sets up a ProtectedResourceDetailsService
called resourceDetails
using the oauth:resource-details-service
tag. It then sets up the OAuthConsumerContextFilter
and OAuthConsumerProcessingFilter
with a reference to resourceDetails
by using the oauth:consumer
tag. These filters are created with instances of ProtectedResourceDetails
for each of the protected resource providers by using the oauth:resource
tag.
来自tonr的applicationContext.xml:
From tonr's 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
和 googleService
创建bean,每个bean都有自己的内部 OAuthRestTemplate
bean,每个bean都带有一个引用通过 constructor-arg
到相应的 ProtectedResourceDetails
之前创建并注入 ProtectedResourceDetailsService
bean。
Next the sparklrService
and googleService
beans are created, each with their own internal OAuthRestTemplate
bean, each which is provided with a reference via constructor-arg
to the respective ProtectedResourceDetails
which were created previously and injected into the ProtectedResourceDetailsService
bean.
来自tonr的spring-servlet.xml:
From tonr's 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>
我的理解在这里稍微弱一些。部分原因是OAuth2名称空间似乎抽象了更多。此外,看起来Tonr 2的例子还没有像原来的Tonr那样充实。我会尽我所能并在必要时进行编辑。
My understanding is a little bit weaker here. Part of the reason for this is that the OAuth2 namespace appears to abstract away a lot more. Also, it looks like the Tonr 2 example hasn't been fleshed out as well as the original Tonr example. I'll do my best and edit if necessary.
首先创建一个 oauth:client
标签并给出一个引用 InMemoryOAuth2ClientTokenServices
bean。看来这会设置适当的过滤器。然后使用 oauth:resource
为sparklr和Facebook创建 OAuth2ProtectedResourceDetails
bean。
First an oauth:client
tag is created and given a reference to an InMemoryOAuth2ClientTokenServices
bean. It appears that this sets up the appropriate filters. Then OAuth2ProtectedResourceDetails
beans are created for both sparklr and Facebook with the oauth:resource
.
来自tonr 2的applicationContext.xml:
From tonr 2's 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创建的。这个内部bean通过 constructor-arg
给出了正确的 OAuth2ProtectedResourceDetails
bean的引用。
Next, just like in the previous example each controller or service bean which needs access to a protected resource is created with an internal OAuth2RestTemplate
bean. This internal bean is given a reference to the correct OAuth2ProtectedResourceDetails
bean via constructor-arg
.
来自tonr 2的spring-servlet.xml:
From tonr 2's 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>
这篇关于尝试在Spring MVC中使用OAuth保护资源的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!