澳门新葡萄京官网首页 1

OAuth 2 开发人员指南(Spring security oauth2)

Java OAuth 2.0 客户端编程(一):
资源所有者密码凭据授权

new無语 转载请注明原创出处,谢谢!

Spring Security学习目录

Java OAuth 2.0 客户端编程(二):
客户端凭据授权

OAuth 2.0 Provider机制负责暴露OAuth
2.0受保护的资源。配置包括建立独立OAuth
2.0客户端可以访问受保护资源。提供者通过管理和验证OAuth
2.0令牌用于访问受保护的资源。在适用情况下,提供者必须提供一个接口,让用户确认客户端有权限访问受保护的资源。

入门

这是支持OAuth2.0的用户指南。对于OAuth1.0,一切都是不同的,所以看它的用户指南。

本用户指南分为两个部分,第一部分是OAuth2.0提供端(OAuth 2.0
Provider),第二部分是OAuth2.0的客户端(OAuth 2.0 Client)

Java OAuth 2.0
客户端编程(三):认证码授权

OAuth
2.0提供者角色实际上是分开授权服务和资源服务,虽然有时会在同一个应用程序中,但是使用Spring Security OAuth,您可以选择将它们拆分为两个应用程序,还可以有多个共享的资源服务授权服务。对令牌的请求由Spring MVC Controller端点处理,受保护资源的访问由标准的Spring Security请求过滤器处理。为了实现OAuth
2.0授权服务器,Spring Security过滤器链中需要以下端点:

OAuth2.0提供端

OAuth2.0的提供端的用途是负责将受保护的资源暴露出去。配置包括建立一个可以访问受保护的资源的客户端代表。提供端是通过管理和验证可用于访问受保护的资源的OAuth
2令牌来做的。在适当的地方,提供端也必须为用户提供一个用于确认客户端
是否能够访问受保护的资源的接口(也就是一个页面或是一个窗口)。

在 OAuth 2
提供者其实是分成授权服务和资源服务两个角色的,而这两个角色有时是存在于同一个应用程序中的,通过 Spring
Security
OAuth 你可以有选择的将它们分裂到两个应用程序中,也可以有选择的给授权服务配置多个资源服务。获取令牌(Tokens)的请求是由Spring
MVC的控制器端点来处理的,访问受保护的资源是通过标准的Spring
Security请求过滤器来处理的。

下面列举的端点是 Spring
Security 过滤器链实现 OAuth 2
授权服务器必须的端点:

  • AuthorizationEndpoint  是用于授权服务请求的。默认的URL是:/oauth/authrize。

  • TokenEndpoint  是用于获取访问令牌(Access
    Tokens)的请求。默认的URL是:/oauth/token。

下面过滤器是实现一个OAuth2资源服务器所必须的:

  • OAuth2AuthenticationProcessingFilter 这个过滤器是用于加载请求提供的一个授权了的访问令牌是否有效。

对于所有的OAuth 2.0的提供端,通过使用Spring
OAuth专门的@Configuration适配器来简化配置。也可以通过XML命名空间来配置OAuth,XML的schema存在:http://www.springframework.org/schema/security/spring-security-oauth2.xsd。命令空间是

概述

OAuth
是一个开放的授权标准,允许客户端代表一个资源所有者获得访问受保护服务器资源的访问权。资源所有者可以是另一个客户端或最终用户。OAuth
还可以帮助最终用户将对其服务器资源的访问权限授权给第三方,而不必共享其凭据,比如用户名和密码。本系列文章遵循
RFC 6749 中所列出的 OAuth 2.0 授权框架。可以在 Internet Engineering Task
Force 的网站上找到 RFC 6749 中列出的完整 OAuth 2.0
授权框架(请参阅 参考资料)。

  • AuthorizationEndpoint用于为授权请求提供服务。默认网址:/oauth/authorize
  • TokenEndpoint用于服务访问令牌的请求。默认网址:/oauth/token

授权服务器配置

配置授权服务器时,您必须考虑的grant类型,从终端用户那,客户端会使用获取到的访问令牌(如授权代码、用户凭证、刷新令牌)。服务器的配置是用于提供一些实现,像客户端细节服务和令牌服务还有启用或禁用某些方面的全球机制。但是请注意,每个客户端可以专门配置权限能够使用某些授权机制和访问授权。即仅仅因为您的提供者配置为支持“客户证书”grant类型,并不意味着一个特定的客户端被授权使用grant类型。

@EnableAuthorizationServer 注释用于配置 OAuth 2.0
授权服务器机制,加上任意一个@Beans 去实现 AuthorizationServerConfigurer
(这是一个hander适配器实现的空方法)。以下功能委托给由 spring 创造的独立
configurers 而且传递到 AuthorizationServerConfigurer:

  • ClientDetailsServiceConfigurer:这个configurer定义了客户端细节服务。客户详细信息可以被初始化,或者你可以参考现有的商店。

  • AuthorizationServerSecurityConfigurer:在令牌端点上定义了安全约束。

  • AuthorizationServerEndpointsConfigurer:定义了授权和令牌端点和令牌服务

提供端配置中重要的一项是提供给OAuth 客户端的授权码。 OAuth
客户端通过将终端用户导向一个可以输入证书/口令的授权验证页面来获取授权码,然后,将授权码传递给提供端授权服务器,服务器验证后重定向页面。
在 OAuth 2 说明文档中有详细的示例。

在 xml 配置文件中,可以使用<authorization-server/>节点配置 OAuth
2.0 授权服务器。

授权批准

授权批准是一种凭据,可代表资源所有者用来访问受保护资源的权限。客户端使用此凭据获取访问令牌。访问令牌最终与请求一起发送,以便访问受保护资源。OAuth
2.0 定义了四种授权类型:

  1. 授权码
  2. 隐式
  3. 资源所有者密码凭据
  4. 客户端凭据

本文是由四部分组成的系列中的第 1
部分,将引导您使用上面列出的每种授权类型在 Java™ 编程中实现 OAuth 2.0
客户端。在第 1
部分中,我会告诉大家如何实现资源所有者密码凭据授权。本文详细介绍各种授权,并解释示例客户端代码,此代码可用于兼容
OAuth 2.0
的任何服务器接口,以支持此授权。在本文的最后,您应该对客户端实现有全面的了解,并准备好下载示例客户端代码,自己进行测试。

以下过滤器是实现OAuth 2.0资源服务器所必需的:

配置客户端详细步骤

ClientDetailsServiceConfigurer 类(AuthorizationServerConfigurer类中的一个调用类)可以用来定义一个基于内存的或者JDBC的客户端信息服务。 

客户端对象重要的属性有:

  • clientId:(必须)客户端id。

  • secret:(对于可信任的客户端是必须的)客户端的私密信息。

  • scope:客户端的作用域。如果scope未定义或者为空(默认值),则客户端作用域不受限制。

  • authorizedGrantTypes:授权给客户端使用的权限类型。默认值为空。

  • authorities:授权给客户端的权限(Spring普通的安全权限)。

在运行的应用中,可以通过直接访问隐藏的存储文件(如:JdbcClientDetailsService中用到的数据库表)或者通过实现ClientDetailsManager 接口(也可以实现ClientDetailsService 接口,或者实现两个接口)来更新客户端信息。

管理令牌

AuthorizationServerTokenServices 接口里定义了
OAuth 2.0 令牌的操作方法。 注意以下几点:

  • 创建一个访问令牌时,必须保存权限信息,这样后续令牌才可以引用它。

  • 访问令牌用于加载创建令牌时的授权信息。

创建AuthorizationServerTokenServices 接口的实现类时,你可以考虑使用DefaultTokenServices 类,它使用随机值创建令牌,并处理除永久令牌以外的所有令牌,对于永久令牌,它委托TokenStore类进行处理。
令牌默认采用基于内存实现的存储方式,但也有一些其它的存储方式。
下面是其中一些方式的简介:

 

  • 默认的InMemoryTokenStore 处理类对于单服务器场景非常适用(优点有:低阻塞,宕机时无需热切换到备份服务器)。大部分项目可以在开始时或者在开发模式下使用这种方式,这样比较容易启动一个没有其它依赖的服务器。

  • JdbcTokenStore 类是实现存储令牌的JDBC
    版本,它将令牌信息保存到关系型数据库中。
    如果服务器间共享数据库或者同一个服务器有多个实例或者授权服务器、资源服务器有多个组件,那么可以使用JDBC方式存储令牌。
    使用JdbcTokenStore 类时,需要将spring-jdbc组件jar包添加到工程的编译路径中。

  • JSON网页令牌(JWT)可以加密所有令牌授权访问的数据(因此不需要在后台存储数据,这就是JWT一个重要的优点)。
    缺点是你不能方便地撤销一个已授权的令牌(因此一般它们被授权的有效期较短,撤销授权的操作在刷新令牌中进行)。
    另一个缺点是存储的令牌数据会越来越大因为在令牌里面存储了大量的用户证书信息。
    JwtTokenStore 类不是一个真正的存储类,它未持久化(保存)任何数据,但是它在传输令牌信息和授权信息(在DefaultTokenServices类中实现)中扮演了同样的角色。
    JwtTokenStore(接口)类依赖JwtAccessTokenConverter类,授权服务器和资源服务器都需要接口的实现类(因此他们可以安全地使用相同的数据并进行解码)。
    令牌以默认方式进行签名,资源服务器为了能够验证这些签名,它需要有与授权服务器相同的对称密钥(服务器共享对称密钥),或者它需要有可以匹配签名私钥的公钥(公有私有密钥或混合密钥)。
    为了使用JwtTokenStore 类,你需要在工程编译路径下添加spring-security-jwt组件jar包(你可以在Spring
    OAuth的github资源库中找到,但是两者的版本号是不一致的)。

 

资源所有者密码凭据授权

当资源所有者对客户端有高度信任时,资源所有者密码凭据授权类型是可行的。此授权类型适合于能够获取资源所有者的用户名和密码的客户端。对于使用
HTTP 基础的现有企业客户端,或者想迁移到 OAuth
的摘要式身份验证,该授权最有用。然后,通过利用现有凭据来生成一个访问令牌,然后就可以实现迁移。

例如,Salesforce.com 添加了 OAuth 2.0
作为对其现有基础架构的一个授权机制。对于现有的客户端转变为这种授权方案,资源所有者密码凭据授权将是最方便的,因为他们只需使用现有的帐户详细信息(比如用户名和密码)来获取访问令牌。

  • OAuth2AuthenticationProcessingFilter用于加载给定的认证访问令牌请求的认证。

Grant 类型

AuthorizationEndpoint 通过 AuthorizationServerEndpointsConfigurer
可以配置支持 Grant 类型。默认情况下支持所有的 grant
类型,除了密码(有关详细信息,请参阅下面的信息如何开启和关闭)。以下属性影响grant类型:
    •
authenticationManager:密码授予被注入一个authenticationManager开启。
    •
authorizationCodeServices:为了身份验证代码授予定义了授权代码服务(org.springframework.security.oauth2.provider.code.AuthorizationCodeServices实例).
    • implicitGrantService:在隐式授予管理状态。
    •
tokenGranter:TokenGranter(完全掌控的授予和忽略上面的其他属性)
在XML
grant类型包括authorization-server的子元素。

图 1. 资源所有者密码凭据流

澳门新葡萄京官网首页 1

在 图 1 中所示的流程包括以下步骤:

  1. 资源所有者提供一个可信的 OAuth 2.0 客户端,并提供其用户名和密码。
  2. OAuth 2.0
    客户端对授权服务器的令牌端点发出访问令牌请求,其中包括从资源所有者那里收到的凭据。在发出请求时,OAuth
    2.0 客户端使用由授权服务器提供的凭据和授权服务器进行身份验证。
  3. 授权服务器对 OAuth 2.0
    客户端进行身份验证,并验证资源所有者凭据,如果该凭据是有效的,那么授权服务器会颁发一个访问令牌。

在配置授权服务器时,必须考虑客户端用来从用户获取访问令牌(例如,授权码,用户凭据,刷新令牌)的授予类型。服务器的配置用于提供客户端详细信息服务和令牌服务的实现。该@EnableAuthorizationServer注释用于配置的OAuth
2.0授权服务器机制,与任何一起@Beans澳门新葡萄京官网首页 ,实现AuthorizationServerConfigurer。以下功能委托给由Spring创建并分配到的配置器AuthorizationServerConfigurer

配置端点的URL

AuthorizationServerEndpointsConfigurer有一个pathMapping()方法。该方法有两个参数:

  • defaultPath 默认的端点URL

  • customPath 自定义的URL 

框架自己提供的URL路径是/oauth/authorize(授权端),/oauth/token
(令牌端),/oauth/confirm_access
(用户发送确认授权到这里),还有/oauth/error
(用户呈现授权服务器授权出错的请求)。

注意:授权端/oauth/authorize(或者是它的影射)应该是受Spring
Security保护的,所以它只能被已授权的用户访问。令牌端默认是通过使用支持使用HTTP基本身份验证客户机的秘密的注解@Configuration,被Spring
Oauth保护的,但不是使用XML文件的(所以在这种情况下它被保护是很明确的)。

使用XML的<authorization-server/>元素可以使用一些属性来达到改变默认的端点URL。

自定义错误处理

授权服务器上错误处理使用标准的 Spring MVC 功能,即 @ExceptionHandler
端点本身的方法。用户还可以提供一个 WebResponseExceptionTranslator
端点本身,最好的办法是改变响应的内容而不是他们呈现的方式。异常的呈现代表
HttpMesssageConverters
(这个可以添加到MVC的配置中)令牌的端点和OAuth的错误视图(/ OAuth
/error)的授权端点。提供一个whitelabel错误端点,但是用户可能需要提供一个自定义的实现(例如,就添加一个
@Controller,它的请求映射是 @RequestMapping(“/ oauth /error”))。

配置资源服务器

资源服务器(可能和授权服务器或者一个单独的应用程序在同一台主机上)提供被OAuth2
令牌保护的资源。 Spring OAuth提供一个Spring
Security授权过滤器,它实现保护资源的功能。在@Configuration类中,你可以使用@EnableResourceServer来开启/关闭过滤器,使用ResourceServerConfigurer来配置它。
下面是可配置的属性:

  • tokenServices:定义令牌服务的实体(ResourceServerTokenServices类的实例)。

  • resourceId:资源ID(可选的,建议配置,如果不为空,授权服务器会对它进行验证)。

@EnableResourceServer注解把一个 OAuth2AuthenticationProcessingFilter 类型过滤器添加到Spring
Security 过滤链中。

在 XML中,有一个<resource-server/>元素,它有一个id属性 –
这是servlet过滤器的bean id,它过滤哪些可以被添加到Spring Security链中。

访问令牌请求

对应于第二个步骤的访问令牌请求如 图 1 所示。

客户端对令牌端点(授权服务器)发出请求,采用
application/x-www-form-urlencoded 格式发送以下参数。

  • grant_type:必选项。必须将其值设置为 “password”
  • username:必选项。资源所有者的用户名。
  • password:必选项。资源所有者密码。
  • scope:可选项。访问请求的范围

如果客户端类型是机密的,或客户端获得了客户端凭据(或者被分配了其他身份验证要求),那么客户端必须向授权服务器进行身份验证。例如,客户端使用传输层安全性发出下列
HTTP 请求。

  • ClientDetailsServiceConfigurer:定义客户端详细信息服务的配置器。客户详细信息可以初始化,或者您可以引用现有的store。
  • AuthorizationServerSecurityConfigurer:定义令牌端点上的安全约束。
  • AuthorizationServerEndpointsConfigurer:定义授权和令牌端点以及令牌服务。

配置OAuth-Aware表达式处理器

你可能想要使用Spring
Security的使用表达式语言配置访问控制的优点。
表达式处理器在 @EnableResourceServer配置中以默认方式进行注册。
表达式包括#oauth2.clientHasRole,#oauth2.clientHasAnyRole,
和 #oath2.denyClient,这些可以提供基于oauth客户端角色的访问控制(详细列表见OAuth2SecurityExpressionMethods)。
在XML中,你可以在<http/> 安全配置节点内使用expression-handler元素注册一个oauth-aware表达式处理器。

清单 1. 向授权服务器进行身份验证
POST /token HTTP/1.1
Host: server.example.com
Authorization:Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
Content-Type: application/x-www-form-urlencoded
grant_type=password&username=varun&password=ab32vr

提供程序配置的一个重要方面是将授权代码提供给OAuth客户端的方式。OAuth客户端通过将最终用户导向授权页面来获得授权码,其中用户可以输入其凭证,再从授权服务器重定向到具有授权码的OAuth客户端。

OAuth 2.0 客户端

OAuth 2.0 客户端控制着 OAuth 2.0保护的其它服务器的资源的访问权限。
配置包括建立相关受保护资源与有权限访问资源的用户之间的连接。
客户端也需要实现存储用户的授权代码和访问令牌的功能。

 

访问令牌响应

对应于上述步骤 C 的访问令牌响应如 图
1 所示。如果访问令牌请求是有效的,并且获得了授权,那么授权服务器将返回访问令牌和一个可选的刷新令牌。清单
2 显示了一个成功响应的示例。

ClientDetailsServiceConfigurer客户端详细信息ClientDetailsServiceConfigurer可用于定义一个内存或JDBC客户端的实现服务细节。重要属性:

受保护资源的配置

受保护的资源(或称为远程资源)可以使用OAuth2ProtectedResourceDetails类型的实体bean定义。
一个受保护的资源有以下属性:

  • id:资源id。它仅在客户端搜索资源的时候使用;在OAuth协议中它从未被用到。它也被用作bean的id。

  • clientId:OAuth客户端id。OAuth提供端依赖这个id来识别客户端。

  • clientSecret:与资源有关的秘密。默认情况下,该值不为空。

  • accessTokenUri:提供访问口令的OAuth提供者终端的统一资源标识符(URI)。

  • scope:以逗号分隔的字符串列表,标识可访问资源的范围。默认情况下,该值为空。

  • clientAuthenticationScheme:
    客户端对访问的令牌终端授权时使用的机制。
    建议值: “http_basic” 和 “form”。 默认值: “http_basic”。 见OAuth
    2 帮助文档2.1节。

不同的授权类型有不同的实现OAuth2ProtectedResourceDetails (对于client_credentials授权类型,使用ClientCredentialsResource )的方式。对于需要进行用户身份验证的授权类型,还有一个属性:

  • userAuthorizationUri: 用户访问资源需要身份验证时跳转页面的URI。
    注意这个字段不是必填的,它依赖于被支持的OAuth 2的配置文件类型。

在XML中,可以使用<resource/>元素创建一个OAuth2ProtectedResourceDetails类型的实体bean。
它有上面提到的所有的属性。

使用@EnableOAuth2Client对OAuth2.0的客户端的配置比较简单。主要要做两件事情:

  • 创建一个过滤bean(用oauth2ClientContextFilter)来存储当前的请求和上下文。在这种情况下需要在请求期间授权,来管理从重定向的位置和OAuth已认证的url。

  • 在请求作用域中创建一个AccessTokenRequest类型的bean。这个类型的bean可以在个人用户的冲突中被识别码识别(或隐式的),授权客户端保持授权状态。

这个过滤器需要能够连接到应用(例如,使用Servlet初始化程序或者web.xml配置文件配置 一个和DelegatingFilterProxy相同名称的代理)。

在一个OAuth2RestTemplate中AccessTokenRequest可以这样使用:

@Autowired
private OAuth2ClientContext oauth2Context;

@Bean
public OAuth2RestTemplate sparklrRestTemplate() {
    return new OAuth2RestTemplate(sparklr(), oauth2Context);
}

OAuth2ClientContext可以在Session的作用域中保持不同用户不同的状态。如果没有这个功能,你需要在你自己的服务强上管理等效的数据结构,映射不用用户进来的请求并且用相互隔离的OAuth2ClientContext实例连接各个用户。

在XML文件中,有一个带有id属性的<client/>标签用于表示servlet的Filter的bean
id,这个必须映射成一个和DelegatingFilterProxy有相同名称的@Configuration注解。

清单 2. 成功的访问令牌响应
    HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache

{
"access_token":"2YotnFZFEjr1zCsicMWpAA",
"token_type":"example",
"expires_in":3600,
"refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA",
"example_parameter":"example_value"
}

如果请求无效,或者是未经授权的,那么授权服务器将会使用代码返回一个相应的错误消息。

  • clientId:客户端ID。
  • secret:客户端密钥
  • scope:客户受限的范围。如果范围未定义或为空,则客户端不受范围的限制。
  • authorizedGrantTypes:授予客户端使用的授权类型。默认值是空的。
  • authorities:授予客户的机构。

访问受保护的资源

一旦,你已经提供了所有的资源服务器配置时,现在你可以访问这些资源。建议的访问这些资源是通过使用在Spring3中提到的RestTemplate。Spring
Security
OAuth已经提供了一个扩展的RestTemplate,只需要提供一个OAuth2ProtectedResourceDetails的实例。使用它与user-tokens(授权代码授予)你应该考虑使用@EnableOAuth2Client配置(或XML等价<
oauth:rest-template /
>),造成了一些请求和会话作用域上下文对象,要求不同的用户在运行时不发生冲突。

设置

示例 OAuth 2.0 客户端被附加为可导入 Eclipse 环境中的 Java
项目。您需要将第三方依赖关系 JAR 文件下载到 Java 项目中的 lib 文件夹中。

客户端详细信息可以通过直接访问底层存储(例如数据库表JdbcClientDetailsService)或通过ClientDetailsManager接口(这两种实现ClientDetailsService也可以实现)在正在运行的应用程序中更新。

客户端持久化访问令牌

客户端不需要持久化令牌,但是它可以很好的用户不需要批准一个新的令牌格兰特每次重新启动客户机应用程序。ClientTokenServices接口定义所需的操作持续OAuth
2.0为特定用户令牌。提供一个JDBC实现,但是如果你喜欢的话你可以实现自己的服务以存储的访问令牌持久数据库和相关的验证实例。如果你想使用此功能,你需要提供一个专门配置TokenProvider
theOAuth2RestTemplate如

@Bean@Scope(value = "session", proxyMode = ScopedProxyMode.INTERFACES)public OAuth2RestOperations restTemplate() {
    OAuth2RestTemplate template = new OAuth2RestTemplate(resource(), new DefaultOAuth2ClientContext(accessTokenRequest));
    AccessTokenProviderChain provider = new AccessTokenProviderChain(Arrays.asList(new AuthorizationCodeAccessTokenProvider()));
    provider.setClientTokenServices(clientTokenServices());
    return template;}

依赖关系 JAR 文件

该项目使用以下 JAR 文件:

  • commons-codec-1.6.jar
  • commons-logging-1.1.1.jar
  • httpclient-4.2.5.jar
  • httpclient-cache-4.2.5.jar
  • httpcore-4.2.4.jar
  • httpmime-4.2.5.jar
  • json-simple-1.1.1.jar

在前六项中提到的 JAR 文件可以在 Http Components JAR
文件中找到。下载这些文件和 json-simple-1.1.1.jar
文件的链接,请参见 更多下载。确保已将下面这些可供下载的
JAR 文件复制到 Java 项目的 lib 文件夹。

令牌管理AuthorizationServerTokenServices接口定义了所必需的管理OAuth
2.0令牌的操作。请注意以下几点:

为外部 OAuth2 提供者定制客户端

一些外部OAuth2提供商(如Facebook)不完全实现正确规范,否则他们只是困在一个旧版本比Spring
Security
OAuth的规范。在您的客户机应用程序使用这些供应商可能需要适应客户端基础设施的各个部分。

使用Facebook作为一个例子,有一个Facebook功能tonr2应用程序(您需要更改配置添加你自己的,有效的,客户机id和秘密,他们很容易生成在Facebook网站上)。

Facebook响应令牌也包含一个不一致的、有失效时间的JSON实体(他们使用到期而不是expires_in),所以如果你想在应用程序中使用失效时间你将不得不使用一个自定义OAuth2SerializationService手动解码。

先决条件

下载 Eclipse IDE for Java EE
developers,以便设置开发环境,并导入附加项目。相关的链接请参见 更多下载。

  • 创建一个访问令牌时,身份验证必须存储,以便资源接受访问令牌可以引用它。
  • 访问令牌用于加载,用于授权其创建的认证。在创建AuthorizationServerTokenServices实现时,可能要考虑使用DefaultTokenServices可以插入许多策略来更改访问令牌的格式和存储。默认情况下,它通过随机值创建令牌,并处理除委托给它的令牌的持久性以外的所有内容TokenStore。默认存储是一个内存中的实现,还有一些其他的实现可用。其它实现:
  • InMemoryTokenStore
  • JdbcTokenStore
  • JwtTokenStore

OAuth 2.0 客户端

此处讨论的 OAuth 2.0
客户端实现了资源所有者密码凭据授权。本系列文章的后续部分将描述其余授权类型,并继续更新客户端代码。

JWT令牌要使用JWT令牌,需要在授权服务器中使用JwtTokenStore。资源服务器还需要能够对令牌进行解码,因此它们JwtTokenStore依赖JwtAccessTokenConverter,并且Authorization ServerResource Server都需要相同的实现。令牌是默认签名的,并且资源服务器还必须能够验证签名,因此它需要与授权服务器(共享密钥或对称密钥)相同的对称密钥,或者它需要公共密钥与授权服务器(公私密钥或非对称密钥)中的私钥相匹配。公共密钥由授权服务器公开/oauth/token_key端点,默认情况下,访问规则为denyAll()。你可以通过注入AuthorizationServerSecurityConfigurer一个标准的SpEL表达式来打开它(例如permitAll。

输入参数

使用在示例客户端代码下载(请参阅 Download)中提供的
Oauth2Client.config 属性文件向客户端提供所需的输入参数。

  • scope:这是一个可选参数。它代表访问请求的范围。由服务器返回的访问令牌只可以访问
    scope 中提到的服务。
  • grant_type:需要将这个参数设置为 "password",表示资源所有者密码凭据授权。
  • username:用于登录到资源服务器的用户名。
  • password:用于登录到资源服务器的密码。
  • client_id:注册应用程序时由资源服务器提供的客户端或使用者 ID。
  • client_secret:注册应用程序时由资源服务器提供的客户端或使用者的密码。
  • access_token:授权服务器响应有效的和经过授权的访问令牌请求时返回的访问令牌。作为该请求的一部分,您的用户名和密码将用于交换访问令牌。
  • refresh_token:这是一个可选参数,由授权服务器在响应访问令牌请求时返回。然而,大多数端点(比如
    Salesforce、IBMWebSphere® Application Server 和 IBM
    DataPower)对资源所有者密码凭据授权不返回刷新令牌。因此,我的客户端实现不打算考虑刷新令牌。
  • authenticatation_server_url:这表示令牌端点。批准和重新生成访问令牌的所有请求都必须发送到这个
    URL。
  • resource_server_url:这表示需要联系的资源服务器的
    URL,通过将授权标头中的访问令牌传递给它来访问受保护的资源。

要使用JwtTokenStore你的类路径需要spring-security-jwt

清单 3. Oauth2Client 代码
 Properties config = OAuthUtils.getClientConfigProps   (OAuthConstants.CONFIG_FILE_PATH);
 String resourceServerUrl = config.getProperty(OAuthConstants.RESOURCE_SERVER_URL);      
 String username = config.getProperty(OAuthConstants.USERNAME);
 String password = config.getProperty(OAuthConstants.PASSWORD);
 String grantType = config.getProperty(OAuthConstants.GRANT_TYPE);
 String authenticationServerUrl = config
         .getProperty(OAuthConstants.AUTHENTICATION_SERVER_URL);

  if (!OAuthUtils.isValid(username)
    || !OAuthUtils.isValid(password)
    || !OAuthUtils.isValid(authenticationServerUrl)
    || !OAuthUtils.isValid(grantType)) {
  System.out
        .println("Please provide valid values for username, password,
                        authentication server url and grant type");
  System.exit(0);

   }

 if (!OAuthUtils.isValid(resourceServerUrl)) {
 // Resource server url is not valid.
 //Only retrieve the access token
 System.out.println("Retrieving Access Token");
 OAuth2Details oauthDetails = OAuthUtils.createOAuthDetails(config);
 String accessToken = OAuthUtils.getAccessToken(oauthDetails);
 System.out
 .println("Successfully retrieved Access token
  for Password Grant:" + accessToken);
 }
 else {
 // Response from the resource server must be in Json or
 //Urlencoded or xml
 System.out.println("Resource endpoint url:" + resourceServerUrl);
 System.out.println("Attempting to retrieve protected resource");
 OAuthUtils.getProtectedResource(config);
      }

在 清单 3 中的客户端代码读取 Oauth2Client.config
文件中所提供的输入参数。usernamepassword、 authentication server url 和 grant type 的有效值是强制性的。如果配置文件中所提供的资源服务器
URL 是有效的,那么客户端会尝试检索该 URL
中提供的受保护资源。否则,客户端只对授权服务器发出访问令牌请求,并取回访问令牌。以下部分说明了负责检索受保护资源和访问令牌的代码。

授权类型AuthorizationEndpoint可以通过AuthorizationServerEndpointsConfigurer配置支持的授权类型。默认情况下,除了密码之外,所有的授权类型都是受支持的(请参阅下面的关于如何打开的细节)。以下属性影响授权类型:

访问受保护资源

清单 4 中的代码演示了如何使用访问令牌来访问受保护的资源。

  • authenticationManager:通过注入密码来开启密码授权AuthenticationManager
  • userDetailsService:如果你注入一个UserDetailsService或者全局配置(例如GlobalAuthenticationManagerConfigurer),那么刷新令牌授权将包含对用户详细信息的检查,以确保该帐户仍然是活动的。
  • authorizationCodeServices:定义了授权代码服务(AuthorizationCodeServices实例)的身份验证代码授予。。
  • implicitGrantService:在非法授权期间管理状态。
  • tokenGranter:完全掌控授予和忽略上面的其他属性
清单 4. 访问受保护资源
String resourceURL =
config.getProperty(OAuthConstants.RESOURCE_SERVER_URL);
OAuth2Details oauthDetails = createOAuthDetails(config);
HttpGet get = new HttpGet(resourceURL);
get.addHeader(OAuthConstants.AUTHORIZATION,
getAuthorizationHeaderForAccessToken(oauthDetails
.getAccessToken()));
DefaultHttpClient client = new DefaultHttpClient();
HttpResponse response = null;
int code = -1;
  try {
    response = client.execute(get);
    code = response.getStatusLine().getStatusCode();
    if (code >= 400) {
      // Access token is invalid or expired.
      // Regenerate the access token
      System.out.println("Access token is invalid
      or expired.Regenerating access token....");
      String accessToken = getAccessToken(oauthDetails);
      if (isValid(accessToken)) {
    // update the access token
      // System.out.println("New access token:" + accessToken);
      oauthDetails.setAccessToken(accessToken);
      get.removeHeaders(OAuthConstants.AUTHORIZATION);
      get.addHeader(OAuthConstants.AUTHORIZATION,
      getAuthorizationHeaderForAccessToken(oauthDetails
    .getAccessToken()));
      get.releaseConnection();
      response = client.execute(get);
      code = response.getStatusLine().getStatusCode();
    if (code >= 400) {
    throw new RuntimeException("Could not
  access protected resource.
  Server returned http code:"+ code);

     }

   } else {
    throw new RuntimeException("Could not
       regenerate access token");
    }

 }

   handleResponse(response);

配置端点URLAuthorizationServerEndpointsConfigurer有一个pathMapping()方法。它有两个参数:

注意

  • 此方法使用从配置文件检索到的值来填充 OauthDetails bean。
  • 顾名思义,这种方法将尝试从资源服务器检索受保护的资源,因此,您需要创建一个简单的 HttpGet 方法。
  • 为了向资源服务器进行身份验证,需要将访问令牌作为 Authorization
    标头的一部分发送。示例:Authorization:Bearer accessTokenValue
  • 创建一个 DefaultHttpClient 对资源服务器发出一个 get 请求。
  • 如果从资源服务器收到的响应代码是 403 或 401,则用于身份验证的访问令牌可能已过期或无效。
  • 下一步是重新创建访问令牌(清单 5)。
  • 成功地重新生成访问令牌之后,更新 OauthDetails bean
    中的访问令牌值。用新的访问令牌值替换 get 方法中现有的
    Authorization 标头。
  • 现在发出对受保护资源的另一个访问请求。
  • 如果访问令牌有效,而且资源服务器的 URL
    也是正确的,那么您应该可以在控制台中看到响应内容。
  • 端点的默认URL路径
  • 所需的自定义路径

重新生成过期的访问令牌

清单 5 中的代码将会处理已过期访问令牌的重新生成。

框架提供的URL路径是:

清单 5. 重新生成过期的访问令牌
 HttpPost post = new HttpPost(
 oauthDetails.getAuthenticationServerUrl());
 String clientId = oauthDetails.getClientId();
 String clientSecret = oauthDetails.getClientSecret();
 String scope = oauthDetails.getScope();

 List<BasicNameValuePair> parametersBody =
 new ArrayList<BasicNameValuePair>();
 parametersBody.add(new BasicNameValuePair(OAuthConstants.GRANT_TYPE,
 oauthDetails.getGrantType()));
 parametersBody.add(new BasicNameValuePair(OAuthConstants.USERNAME,
 oauthDetails.getUsername()));
 parametersBody.add(new BasicNameValuePair(OAuthConstants.PASSWORD,
 oauthDetails.getPassword()));

 if (isValid(clientId)) {
    parametersBody.add(new BasicNameValuePair
      (OAuthConstants.CLIENT_ID,clientId));
  }
 if (isValid(clientSecret)) {
    parametersBody.add(new BasicNameValuePair(
    OAuthConstants.CLIENT_SECRET, clientSecret));
  }
 if (isValid(scope)) {
    parametersBody.add(new BasicNameValuePair
      (OAuthConstants.SCOPE,scope));
  }

 DefaultHttpClient client = new DefaultHttpClient();
 HttpResponse response = null;
 String accessToken = null;
   try {
    post.setEntity(new UrlEncodedFormEntity(parametersBody,
       HTTP.UTF_8));

    response = client.execute(post);
    int code = response.getStatusLine().getStatusCode();
    if (code >= 400) {
    System.out.println("Authorization
       server expects Basic authentication");
    // Add Basic Authorization header
    post.addHeader(
    OAuthConstants.AUTHORIZATION,
    getBasicAuthorizationHeader(oauthDetails.getUsername(),
    oauthDetails.getPassword()));
    System.out.println("Retry with login credentials");
    post.releaseConnection();
    response = client.execute(post);
    code = response.getStatusLine().getStatusCode();
    if (code >= 400) {
    System.out.println("Retry with client credentials");
    post.removeHeaders(OAuthConstants.AUTHORIZATION);
    post.addHeader(
    OAuthConstants.AUTHORIZATION,
       getBasicAuthorizationHeader(
     oauthDetails.getClientId(),
    oauthDetails.getClientSecret()));
    post.releaseConnection();
    response = client.execute(post);
    code = response.getStatusLine().getStatusCode();
    if (code >= 400) {
    throw new RuntimeException(
    "Could not retrieve access token for user:"
    oauthDetails.getUsername());
       }
        }
      }
    Map<String, String> map = handleResponse(response);
    accessToken = map.get(OAuthConstants.ACCESS_TOKEN);
    } catch (ClientProtocolException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
    } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
    }

    return accessToken;
  • /oauth/authorize:授权端点
  • /oauth/token:令牌端点
  • /oauth/confirm_access:用户在此处批准授权
  • /oauth/error: 用于在授权服务器中渲染错误
  • /oauth/check_token: 由资源服务器用来解码访问令牌
  • /oauth/token_key: 如果使用JWT令牌,公开密钥用于令牌验证

注意

  • 这种方法生成一个 HttpPost 请求,并获得身份验证服务器的 URL。
  • Post 请求以 URL
    编码参数的形式发送 usernamepassword,以及可选的 scope,将它们作为有效载荷的一部分。
  • 有些授权服务器还会要求您发送 client_id 和 client_secret 作为此请求有效载荷的一部分。
  • 如果 client_idclient_secret 和 scope 的值不为空,那么它们也将作为有效载荷的一部分被发送。
  • 按照 OAuth 2.0
    授权框架,客户端应该使用客户端凭据,或使用在发出访问令牌请求时由服务器所提供的其他任何凭据来设置
    Authorization
    标头。但是,这受制于授权服务器实现。客户端代码发出初始请求时无需添加基本身份验证标头。如果服务器返回一个未经授权的响应,客户端随后试图通过登录和客户端凭据进行身份验证。
  • OAuth 2.0 规定,需要采用 JSON
    格式来发送访问令牌响应。但为了灵活性,我还添加了实用程序方法来处理来自服务器的
    XML 编码或 URL 编码的响应。

注意,授权端点/oauth/authorize应该使用Spring Security进行保护,以便只有经过认证的用户才能访问。例如使用标准的Spring Security WebSecurityConfigurer

测试客户端

在本节中,我将讨论如何建立一个 OAuth 2.0 兼容的端点并用它来测试客户端。

 @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests().antMatchers.permitAll // default protection for all resources (including /oauth/authorize) .authorizeRequests() .anyRequest().hasRole // ... more configuration, e.g. for form login }

在 Salesforce.com 注册

Salesforce.com
对于资源所有者密码凭据授权是一个很好的用例。如果用户有登录
Salesforce.com 的凭据,并希望自己的客户端转变为 OAuth 2.0
身份验证,那么他需要做的就是在 Salesforce
注册自己的应用程序,以获得客户端凭据。现在可以用这些客户端凭据以及他现有的登录凭据从授权服务器中获得访问令牌。

  1. 如果您以前没有在 Salesforce.com
    注册过,请立即注册。请参阅 参考资料 。
  2. 单击 Login,然后单击 Sign up for free
  3. 完成注册,获得您的凭据。
  4. 除了用户名和密码之外,您还将获得一个安全令牌。您提供的用于发出访问令牌请求的密码必须是您的密码和安全令牌的串联。(示例:password12312123)。
  5. 有关如何在 salesforce.com
    中创建应用程序,请参阅 参考资料 中有用的文章链接。

授权服务器中的错误处理使用标准的Spring
MVC功能,即@ExceptionHandler端点本身的方法。用户还可以提供WebResponseExceptionTranslator端点本身,这是改变响应内容的最好方式,而不是渲染的方式。异常委托HttpMesssageConverters(在MVC配置中可以添加)以及/oauth/error授权端点的OAuth错误视图。可以自己实现(如只需添加一个@Controller@RequestMapping("/oauth/error"))。

运行客户端

现在,您已经完成了 Salesforce.com
中的注册,您可以测试客户端并从服务器检索受保护的信息。

  • 将本文中讨论的 Java 项目导入到 Eclipse
    工作区(请参阅 参考资料)。
  • 下载依赖关系 JAR 文件,并将其复制到项目的 lib
    文件夹中(请参阅 更多下载 )。
  • 导航到 resources/com/ibm/oauth/Oauth2Client.config
    文件,并填写 usernamepassword(追加安全令牌)、client_idclient_secret 和 authorization server URL 的值。
  • 打开 Oauth2Client.java 并运行它。

不仅限于分配给客户端的范围,还要根据用户自己的权限来限制令牌的范围。如果你DefaultOAuth2RequestFactory在你的系统中使用了AuthorizationEndpoint一个标志checkUserScopes=true,你可以设置一个标志来将允许的范围限制在那些与用户角色匹配的范围内。你也可以注入一个OAuth2RequestFactoryTokenEndpoint但只有工程,如果你也安装一个TokenEndpointAuthenticationFilter,
你只需要在HTTP后面添加该过滤器BasicAuthenticationFilter。当然,你也可以实现自己的规则,将范围映射到角色并安装你自己的版本OAuth2RequestFactory。将AuthorizationServerEndpointsConfigurer让你注入一个定制的OAuth2RequestFactory,所以你可以使用该功能来建立一个工厂,如果你使用@EnableAuthorizationServer

访问令牌输出

您应该在控制台窗口看到下面的输出。

Retrieving Access Token
encodedBytes dmVybi5vamhhQGdtYWlsL.......

********** Response Received **********
  instance_url = https://ap1.salesforce.com
  issued_at = 1380106995639
  signature = LtMjTrmoBbvVfZ6+qT5Un1UioHaV9KIOK7ayQTmJzCg=
  id = https://login.salesforce.com/id/00D90000000mQaYEAU/00590000001HCB7AAO
  access_token = 00D90000000mQaY!AQ8AQEn0rLDMvxrP9WgY3Blc.......
Successfully retrieved Access token for Password Grant:00D90000000mQaY!AQ8AQEn0rLDMvxrP9WgY3Bl......

资源服务器(可以与授权服务器或单独的应用程序相同)为受OAuth2令牌保护的资源提供服务。Spring
OAuth提供了一个实现这种保护的Spring
Security认证过滤器。你可以@EnableResourceServer在一个@Configuration类上打开它,并根据使用需要,进行配置ResourceServerConfigurer。以下功能可以配置:

从 Salesforce.com 检索用户信息

现在,您已经有了访问令牌和 ID,可以向 Salesforce.com 发出请求,通过使用
OAuth 2.0 进行身份验证来访问您的帐户信息。

  • 用访问令牌更新 Oauth2Client.confg
    文件,并使用作为响应的一部分返回的 id 值来填充资源服务器 URL
    属性。
  • 再次运行 Oauth2Client.java。
  • tokenServices:定义令牌服务的bean(实例ResourceServerTokenServices)。
  • resourceId:资源的id(可选,但是推荐,并且将由auth服务器验证,如果存在的话)。
  • resourecs服务器的其他扩展点(例如,tokenExtractor用于从传入请求中提取令牌)
  • 请求受保护资源的匹配器
  • 受保护资源的访问规则(默认为普通“已认证”)
  • HttpSecurity Spring
    Security中配置器所允许的受保护资源的其他自定义。该@EnableResourceServer注释将OAuth2AuthenticationProcessingFilter自动添加到Spring
    Security过滤器链中。如果资源服务器和授权服务器在同一个应用程序中,那么不必过多考虑DefaultTokenServices,因为它实现了所有必需的接口,因此它自动保持一致。如果资源服务器是一个单独的应用程序,那么必须确保匹配授权服务器的功能,并提供一个ResourceServerTokenServices来知道如何正确解码令牌。与授权服务器一样,可以经常使用DefaultTokenServices和选择大部分通过TokenStore(后端存储或本地编码)表示。另一种方法是RemoteTokenServices这是Spring
    OAuth功能,允许资源服务器通过授权服务器(/oauth/check_token)上的HTTP资源来解码令牌。RemoteTokenServices如果资源服务器中没有大量的流量(每个请求都必须使用授权服务器进行验证),或者您能负担得起缓存结果,那么这种方法非常方便。要使用/oauth/check_token端点,你需要通过改变它的访问规则(默认为denyAll中暴露它AuthorizationServerSecurityConfigurer。如:

输出

您应该在控制台窗口看到类似于下面的输出。

清单 6. 输出
Resource endpoint URL: https://login.salesforce.com/id/00D90000000mQaYEAU/00590000001HCB7AAO
Attempting to retrieve protected resource
********** Response Received **********
photos = {"thumbnail":"https:////c.ap1.content.force.com//profilephoto//005//T","picture":"https:///
/c.ap1.content.force.com//profilephoto//005//F"}
urls =
{"enterprise":"https:////ap1.salesforce.com//services//Soap//c//{version}//00D90000000mQaY","sobjects":
"https:////ap1.salesforce.com//services//data//v{version}//sobjects//","partner":"https:///
/ap1.salesforce.com//services//Soap//u//{version}//00D90000000mQaY","search":"https:///
/ap1.salesforce.com//services//data//v{version}//search//","query":"https:////ap1.salesforce.com/
/services//data//v{version}//query//","users":"https:////ap1.salesforce.com//services//data//v{version}/
/chatter//users","profile":"https:////ap1.salesforce.com//00590000001HCB7AAO","metadata":"https:///
/ap1.salesforce.com//services//Soap//m//{version}//00D90000000mQaY","rest":"https:////ap1.salesforce.com/
/services//data//v{version}//","groups":"https:////ap1.salesforce.com//services//data//v{version}/
/chatter//groups","feeds":"https:////ap1.salesforce.com//services//data//v{version}//chatter//feeds",
"recent":"https:////ap1.salesforce.com//services//data//v{version}//recent//","feed_items":"https://
//ap1.salesforce.com//services//data//v{version}//chatter//feed-items"}
  asserted_user = true
  active = true
  organization_id = 00D90000000mQaYEAU
  nick_name = vern.ojha1....
  display_name = varun ojha
  user_type = STANDARD
  user_id = ***********
  status = {"body":null,"created_date":null}
  last_name = ojha
  username = vern.ojha.....
  utcOffset = -28800000
  language = en_US
  locale = en_US
  first_name = varun
  last_modified_date = 2013-06-04T07:43:42.000+0000
  id = https://login.salesforce.com/id/00D90000000mQaYEAU/00590000001HCB7AAO
  email = vern.ojha@gmail.com

如您所见,您可以通过使用 OAuth 2.0
进行身份验证,成功获取用户信息。在配置文件中提供的访问令牌过期后,客户端将会自动重新生成访问令牌,并使用它来检索在资源服务器
URL 中提供的受保护资源。

 @Override public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception { oauthServer.tokenKeyAccess("isAnonymous() || hasAuthority('ROLE_TRUSTED_CLIENT')").checkTokenAccess( "hasAuthority('ROLE_TRUSTED_CLIENT')"); }

用 IBM 端点测试客户端

客户端也已经成功通过 OAuth 2.0 兼容的 IBM 端点的测试,即 IBM WebSphere
Application Server 和 IBM
DataPower。请参阅 参考资料 的链接,“使用
OAuth:在 WebSphere Application Server 中启用 OAuth
服务提供程序”,这是一个非常好的资源,介绍了如何在 WebSphere Application
Server 上设置 OAuth 2.0。

在您的应用服务器上设置了 OAuth 2.0 后,客户端所需的输入与 Salesforce.com
演示中的相同。

在这个例子中,我们正在配置/oauth/check_token端点和/oauth/token_key端点(所以可信资源可以获得JWT验证的公钥)。这两个端点受到使用客户端凭据的HTTP基本身份验证的保护。

结束语

本文是该系列文章的第一部分,阐述了资源所有者密码凭据授权的基础知识。本文演示了如何在
Java 编程中编写一个通用的 OAuth 2.0 客户端,以连接到 OAuth 2.0
兼容的多个端点,并从中获取受保护的资源。示例客户端被附加为一个 Java
项目,以使您能够迅速导入项目到 Eclipse
工作区,并开始测试。在本系列文章的后续部分中,我将介绍在 OAuth 2.0
授权框架中列出的其余三种授权类型。在后续文章中,客户端代码将会获得更新,以反映这些授权类型及特性,比如发布到某个资源服务器和处理
SSL。

OAuth 2.0客户端机制负责访问其他服务器的受OAuth
2.0保护的资源。配置涉及建立用户可能访问的相关受保护资源。客户端可能还需要提供用于存储授权代码和用户访问令牌的机制。

下载

描述 名字 大小
示例客户端代码 OAuth20.zip 19KB

受保护的资源配置受保护的资源可以定义使用OAuth2ProtectedResourceDetails类型的bean。受保护的资源具有以下属性:

  • id:资源的ID。该id只被客户端用来查找资源;
    它从未在OAuth协议中使用过。它也被用作bean的id。
  • clientId:OAuth客户端ID。这是OAuth提供商识别您的客户端的ID。
  • clientSecret:与资源相关的秘钥。默认情况下为空。
  • accessTokenUri:提供访问令牌的提供者OAuth端点的URI。
  • scope:逗号分隔的字符串列表,指定对资源的访问范围。默认情况下,不会指定范围。
  • clientAuthenticationScheme:您的客户端用来验证访问令牌端点的方案。建议值:“http_basic”和“form”。

不同的授权类型有不同的具体实现OAuth2ProtectedResourceDetails(例如ClientCredentialsResource“client_credentials”授权类型)。对于需要用户授权的授权类型,还有一个属性:

  • userAuthorizationUri:如果用户需要授权访问资源,用户将被重定向到的URI。请注意,这并不是必需的,具体取决于支持哪些OAuth
    2配置文件。

客户端配置对于OAuth
2.0客户端,配置使用简化@EnableOAuth2Client。这有两件事情:

  • 创建一个过滤器bean(oauth2ClientContextFilter)来存储当前的请求和上下文。在请求期间需要进行身份验证的情况下,它将管理OAuth身份验证URI中的重定向。
  • AccessTokenRequest在请求范围内创建一个类型的bean
    。这可以被授权代码授权客户端使用,防止与个别用户相关的状态发生冲突。使用
    OAuth2RestTemplate

@Autowiredprivate OAuth2ClientContext oauth2Context;@Beanpublic OAuth2RestTemplate sparklrRestTemplate() { return new OAuth2RestTemplate, oauth2Context);}

OAuth2ClientContext放置在会话范围内,以保持不同用户的状态分离。

访问受保护的资源一旦你提供了资源的所有配置,你现在可以访问这些资源。用于访问这些资源的建议的方法是通过使用RestTemplate,只需要提供一个OAuth2ProtectedResourceDetails。要将其与用户令牌结合使用,您应该考虑使用创建一些请求和会话作用域上下文对象的@EnableOAuth2Client配置(或XML等价物<oauth:rest-template/>),以便不同用户的请求在运行时不会发生冲突。

一般来说,一个网络应用程序不应该使用密码授权,所以ResourceOwnerPasswordResourceDetails请避免使用AuthorizationCodeResourceDetails。如果需要从Java客户端获得密码授权,那么使用相同的机制来配置您OAuth2RestTemplate的证书并将其添加到AccessTokenRequest而不是ResourceOwnerPasswordResourceDetails(所有访问令牌之间共享的)证书。

持久性令牌在客户端客户端不需要持续令牌,用户在每次重新启动客户端应用程序时都不需要批准新的令牌授予就可以了。ClientTokenServices接口定义的操作是必要的,为特定用户持续OAuth
2.0令牌。提供了一个JDBC实现,但如果您愿意实现自己的服务来将访问令牌和关联的身份验证实例存储在持久数据库中,则可以这样做。如果你想使用这个功能,你需要提供一个专门配置TokenProviderOAuth2RestTemplate例如:

@Bean@Scope(value = "session", proxyMode = ScopedProxyMode.INTERFACES)public OAuth2RestOperations restTemplate() { OAuth2RestTemplate template = new OAuth2RestTemplate(resource(), new DefaultOAuth2ClientContext(accessTokenRequest)); AccessTokenProviderChain provider = new AccessTokenProviderChain(Arrays.asList(new AuthorizationCodeAccessTokenProvider; provider.setClientTokenServices(clientTokenServices; return template;}

发表评论

电子邮件地址不会被公开。 必填项已用*标注