首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

使用 Spring Security 保护 Web 应用的安全(8)

使用 Spring Security 保护 Web 应用的安全(8)

OAuth 集成现在的很多 Web 服务都提供 API 接口,允许第三方应用使用其数据。当第三方应用需要访问用户私有数据的时候,需要进行认证。OAuth 是目前流行的一种认证方式,被很多 Web 服务采用,包括 Twitter、LinkedIn、Google Buzz 和新浪微博等。OAuth 的特点是第三方应用不能直接获取到用户的密码,而只是使用一个经过用户授权之后的令牌(token)来进行访问。用户可以对能够访问其数据的第三方应用进行管理,通过回收令牌的方式来终止第三方应用对其数据的访问。OAuth 的工作方式涉及到服务提供者、第三方应用和用户等 3 个主体。其基本的工作流程是:第三方应用向服务提供者发出访问用户数据的请求。服务提供者会询问用户是否同意此请求。如果用户同意的话,服务提供者会返回给第三方应用一个令牌。第三方应用只需要在请求数据的时候带上此令牌就可以成功获取。
第三方应用在使用 OAuth 认证方式的时候,其中所涉及的交互比较复杂。Spring Security 本身并没有提供 OAuth 的支持,通过另外一个开源库 OAuth for Spring Security 可以实现。OAuth for Spring Security 与 Spring Security 有着很好的集成,可以很容易在已有的使用 Spring Security 的应用中添加 OAuth 的支持。不过目前 OAuth for Spring Security 只对 Spring Security 2.0.x 版本提供比较好的支持。对 OAuth 的支持包括服务提供者和服务消费者两个部分:服务提供者是数据的提供者,服务消费者是使用这些数据的第三方应用。一般的应用都是服务消费者。OAuth for Spring Security 对服务提供者和消费者都提供了支持。下面通过获取 LinkedIn 上的状态更新的示例来说明其用法。
作为 OAuth 的服务消费者,需要向服务提供者申请表示其应用的密钥。服务提供者会提供 3 个 URL 来与服务消费者进行交互。中给出了使用 OAuth for Spring Security 的配置文件。
清单 11. 使用 OAuth for Spring Security 的配置文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<oauth:consumer resource-details-service-ref="linkedInResourceDetails"
   oauth-failure-page="/oauth_error.jsp">
   <oauth:url pattern="/linkedin.do**" resources="linkedIn" />
</oauth:consumer>

<bean id="oauthConsumerSupport"
   class="org.springframework.security.oauth.consumer.CoreOAuthConsumerSupport">
   <property name="protectedResourceDetailsService" ref="linkedInResourceDetails" />
</bean>

<oauth:resource-details-service id="linkedInResourceDetails">
   <oauth:resource id="linkedIn"
       key="***" secret="***"
       request-token-url="https://api.linkedin.com/uas/oauth/requestToken"
       user-authorization-url="https://www.linkedin.com/uas/oauth/authorize"
       access-token-url="https://api.linkedin.com/uas/oauth/accessToken" />
</oauth:resource-details-service>




如 所示,只需要通过对 <oauth:resource>元素进行简单的配置,就可以声明使用 LinkedIn 的服务。每个 <oauth:resource>元素对应一个 OAuth 服务资源。该元素的属性包含了与该服务资源相关的信息。OAuth for Spring Security 在 Spring Security 提供的过滤器的基础上,额外增加了处理 OAuth 认证的过滤器实现。通过 <oauth:consumer>的子元素 <oauth:url>可以定义过滤器起作用的 URL 模式和对应的 OAuth 服务资源。当用户访问指定的 URL 的时候,应用会转到服务提供者的页面,要求用户进行授权。当用户授权之后,应用就可以访问其数据。访问数据的时候,需要在 HTTP 请求中添加额外的 Authorization头。给出了访问数据时使用的代码。
清单 12. 获取访问令牌和构建 HTTP 请求
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public OAuthConsumerToken getAccessTokenFromRequest(HttpServletRequest request) {
   OAuthConsumerToken token = null;

   List<OAuthConsumerToken> tokens = (List<OAuthConsumerToken>) request
       .getAttribute(OAuthConsumerProcessingFilter.ACCESS_TOKENS_DEFAULT_ATTRIBUTE);
   if (tokens != null) {
       for (OAuthConsumerToken consumerToken : tokens) {
           if (consumerToken.getResourceId().equals(resourceId)) {
               token = consumerToken;
               break;
           }
       }
   }
   return token;
}

public GetMethod getGetMethod(OAuthConsumerToken accessToken, URL url) {
   GetMethod method = new GetMethod(url.toString());
   method.setRequestHeader("Authorization",
                getHeader(accessToken, url, "GET"));
   return method;
}

public String getHeader(OAuthConsumerToken accessToken, URL url,
            String method) {
   ProtectedResourceDetails details = support
       .getProtectedResourceDetailsService()
       .loadProtectedResourceDetailsById(accessToken.getResourceId());
   return support.getAuthorizationHeader(details, accessToken, url, method, null);
}




如 所示,OAuth for Spring Security 的过滤器会把 OAuth 认证成功之后的令牌保存在当前的请求中。通过 getAccessTokenFromRequest()方法就可以从请求中获取到此令牌。有了这个令牌之后,就可以通过 getHeader()方法构建出 HTTP 请求所需的 Authorization头。只需要在请求中添加此 HTTP 头,就可以正常访问到所需的数据。默认情况下,应用的 OAuth 令牌是保存在 HTTP 会话中的,开发人员可以提供其它的令牌保存方式,如保存在数据库中。只需要提供 org.springframework.security.oauth.consumer.token.OAuthConsumerTokenServices接口的实现就可以了。
返回列表