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

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

OAuth服务器在另一个处理登录和创建访问令牌的网站中实现。 因此,我需要在授予用户访问Web服务的权限之前validation访问令牌是否正确。

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

保护这些Web服务的最佳方法是什么? 什么是入门的最佳方式?

谢谢你的帮助。

重要

[编辑12/27/2012:我在下面引用的教程现在抛出404.在github上有一个稍微更新的本教程版本。 我已经看清了看起来很糟糕的链接。 因为现在缺少的教程是提问者引用的教程,所以现在我将其留给后人。 据我所知,此处包含的信息仍然有用 ,所以也许有一天,当我有时间时,我会根据新教程重写它。

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

背景

我当然可以解决你的文档问题。 Spring Security可以说是任何Spring项目中最陡峭的学习曲线,OAuth支持相当新,并且与Spring Security分开维护。 Spring Security OAuth文档很少。

如果您对OAuth没有良好的感觉,那就去买一个吧! 您要求您的用户信任您网站实施此标准的安全性。 因此,您无法理解您对该主题的理解! 显而易见的起点是OAuth.net和OAuth初学者指南 。

如果/一旦您对OAuth的工作方式有了良好的了解,我强烈建议您阅读Spring Security“ 入门 ”和“ 文章和教程 ”文档列表,以便更好地了解Spring Security的实现方式。

一旦掌握了Spring Security的相关知识和对OAuth的正确认识,官方的Spring Security OAuth 用户指南就会开始变得有意义。 对于您正在使用的OAuth版本( 1.02.0 ),您需要特别关注消费者/客户端部分。

同一个站点也有一个体面的OAuth 1.0和OAuth 2.0 教程 ,它基于上面提到的服务OAuth初学者指南的第二部分。

访问受保护的Restful资源

对于您的问题,我们将重点关注上述教程中Tonr照片打印服务的实施。 此服务打印的照片是由外部网站托管的受OAuth保护的资源。 Tonr推迟到这些站点访问这些资源。 这将包括重定向用户以进行用户身份validation和必要时的身份validation确认。

Spring-MVC REST服务/控制器本身是外部OAuth保护资源的消费者,它通过使用请求filter来实现这种“延迟授权”(我的术语)行为。 根据1.0 用户指南

有两个适用于OAuth使用者逻辑的请求筛选器。 第一个filterOAuthConsumerContextFilter负责建立特定于OAuth的安全上下文,与Spring Security的SecurityContext非常相似。 安全上下文只包含一组为当前用户获取的访问令牌。 在发出受保护资源请求时会利用此安全上下文。

还有另一个请求filterOAuthConsumerProcessingFilter ,可应用于需要访问远程受保护资源的特定URL或URL模式。 将此filter放在Spring Security的filter链中将确保在允许访问资源之前获取指定URL模式所需的任何访问令牌。

正如您所看到的,对于OAuth 1.0,使用有效的OAuthConsumerProcessingFilter过滤请求将处理获取有效访问令牌的所有内容,并在访问被拒绝时通知用户。 同样,还有相应的OAuth2ClientContextFilterOAuth2ClientProcessingFilter类。

最后,一旦完成设置,您就可以使用OAuthRestTemplateOAuth2RestTemplate访问控制器中受OAuth保护的资源,就像使用正常的RestTemplate访问不受保护的资源RestTemplate ( 此处为 info)。 但是,必须使用ProtectedResourceDetails或OAuth2ProtectedResourceDetails实例将它们注入服务或控制器。

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

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

如果您想在使用OAuth名称空间的情况下查看提供者方的工作方式,我建议您查看此SpringSource论坛post ,并按照SECOAUTH-53的问题进行更新。

OAuth 1.0示例

Tonr在这里使用Sparklr和Google的OAuth保护服务,因此它使用oauth:resource-details-service标签设置名为resourceDetailsProtectedResourceDetailsService 。 然后,它使用oauth:consumer标记设置OAuthConsumerContextFilterOAuthConsumerProcessingFilter ,并引用resourceDetails 。 这些filter是使用oauth:resource标记为每个受保护资源提供程序创建的ProtectedResourceDetails实例。

来自tonr的applicationContext.xml:

             

接下来创建sparklrServicegoogleService bean,每个bean都有自己的内部OAuthRestTemplate bean,每个bean都通过constructor-arg给之前创建并注入ProtectedResourceDetailsService bean的相应ProtectedResourceDetailsService

从tonr的spring-servlet.xml:

                 

OAuth 2.0示例

我的理解在这里有点弱。 部分原因是OAuth2名称空间似乎抽象了更多。 此外,看起来Tonr 2的例子还没有像原来的Tonr那样充实。 我会尽我所能并在必要时进行编辑。

首先创建一个oauth:client标签,并给出对InMemoryOAuth2ClientTokenServices bean的引用。 看来这会设置适当的filter。 然后使用oauth:resource为sparklr和Facebook创建OAuth2ProtectedResourceDetails bean。

从tonr 2的applicationContext.xml:

        

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

从tonr 2的spring-servlet.xml: