您的位置:首页 > 编程语言 > Java开发

粗略翻译:Spring Oauth2 官方文档(OAuth 2 Developers Guide)

2017-06-22 11:22 513 查看
前言:

最近在使用Spring OAuth2.0来搭建一个单点登录的系统,查看了一些文档,自己做了一些粗浅的翻译(毕竟英文水平太LOW)。有些地方用了Google的机翻。磕磕绊绊,总之是完成了。勉强凑合能看。

下面是正文:

OAuth2.0 provider(提供者)

OAuth2.0提供者机制为暴露Oauth2保护的资源提供了可能。配置涵盖了建立OAuth2.0客户端,这个客户端可以独立的访问它保护的资源或者代替用户访问。这个Provider通过管理和核查OAuth2.0用来访问保护资源的tokens来实现访问资源的功能。可能的情况下,Provider还需要给用户提供一个可以授权进入保护资源的接口 。

Oauth2.0 Provider 实现

Oauth2.0 的 Provider规则实际上被分割成Authorization Service(授权服务)和Resource Service(资源服务),当他们在一个Spring Security Oauth应用中,你可以选择将他们分成两个不同的应用或者多个资源服务共享一个授权服务。tokens的请求被Spring MVC的Controller处理,进入保护资源的动作是通过Spring Security 请求Filters(过滤器)来处理。

下面列出的endpoints(终端)在Spring Security过滤链中用来实现Oauth2.0的授权服务。

AuthorizationEndpoint :用来处理授权请求,默认的请求URL:/oauth/authorize

TokenEndpoint: 用来处理access tokens请求,默认的URL: /oauth/token

下面的过滤器用来实现一个OAuth2.0的资源服务

OAuth2AuthenticationProcessingFilter:被用来加载一个鉴定带有已认证的access token 请求的Authen(鉴定器)

对于完全的OAuth2.0的Provider的特征,可以通过使用Spring Oauth @Configuration适配器来简单的配置。或者也可以使用XML的OAuth命名空间配置。标准的 schema(描述)在http://www.springframework.org/schema/security/spring-security-oauth2.xsd ,命名空间的配置在 http://www.springframework.org/schema/security/oauth2。
Authorization Server(授权服务器)配置

当你配置一个授权服务器的时候,你需要考虑client(客户端)经常从终端用户处获得一个access token的授权类型。(例子:authorization code ,user credentials , refresh token )。这个服务器配置用来提供client details service (客户端描述服务)和token services (token服务)和 全局的某些机制的实现。注意,无论何时,客户端都可以被明确的配置是否使用某些机制和拥有准入授权的权限。也就是说,只是因为你的provider配置了支持client
credentials授权类型,并不意味着一个特殊的客户端有权使用这个授权类型。

@EnableAuthorizationServer注解和任何实现了AuthorizationServerConfigurer的@Bean(已经有一个便利的适配器实现了接口,但是方法都是空的。)一起用来配置OAuth2,0的授权服务机制。下面的各个Configurer是配置全部AuthorizationServerConfigurer的各个部分,他们被Spring组织起来完成整个AuthorizationServerConfigurer的配置。

ClientDetailsServiceConfigurer:定义ClientDetailsSercvice(客户端描述服务)的配置对象。Client details可以配初始化或者参考一个已经存在的存储。

AuthorizationServerSecurityConfigurer:定义在token终端上的安全约束条件。

AuthorizationServerEndpointsConfigurer:用来定义授权,token终端和token服务器

Provider配置的一个很重要的方面是授权码被提供给一个Oauth客户端的方式(在 authorization code授权中)。客户端获得一个授权码是用过重定向终端用户去一个授权页面,在这个授权页面上,用户可以输入他们的凭证(用户名,密码,或者其他证明自己身份的协议)。用户获得一个客户端页面,拥有授权码的返回。这个执行过程的例子在OAuth2的说明中有详细的例子。

在XML的配置中使用<authorization-server>配置。

配置一个Client Details

ClientDetailsServiceConfigurer可以使用一个定义 in-memory或者定义一个JDBC实现ClientDetailsService。一个客户端的重要的属性是:

clientId:(必要)客户端id;(数据库中的主键)

secret:(信任客户端必要)客户端密码,或者没有

scope:客户端的限制范围,如果它是null或者没有定义,那么客户端没有限制范围

authorizedGrantTypes:授权类型,用来指定客户端可以被授权的类型,默认是空

authorities:客户端被赋予的权限。

Client details可以被更新在一个正在执行的应用中,通过更底层的保存接口(数据库的表,利用JdbcClientDetailsService)或者通过ClientDetailsManager接口(它同时实现了ClientDetailsService)。

注意:JDBC的描述文件没有包含在库中,在github上有一个例子,地址:https://github.com/spring-projects/spring-security-oauth/blob/master/spring-security-oauth2/src/test/resources/schema.sql

实际上你可能需要各种符合业务的ClientDetails。(官方的意思是,上面那几个属性你应该有,剩下的,根据需要自己修改)

管理Tokens

AuthorizationServerTokenServices接口定义了管理OAuth2.0 tokens必须要的一些选项。

注意下面两项:

1.当一个access token被创建了。这个认证必须被存储,所以这个来源所同意的access token能在晚些时候被验证。

2.access token 被用来加载认证创建者的认证。

当创建一个你自己的AuthorizationServerTokenServices的实现,你可以考虑使用DefaultTokenServices,它有一些能插入改变格式和存储access tokens的策略。默认情况下,它建立tokens通过随机值和处理所有事情,除非tokens的保存指定了它的tokenStore。默认的存储是in-memory实现。但是这又一些其他的实现参数,下面是关于他们的详细说明。

1.默认的InMemoryTokenStore是完美的,对于一个单独的服务器来说(也就是低传输和没有热备策略的服务器)。多数的项目可以由此开始,是一个给开发人员的易用的方式,可以不用开发代码。

2.JdbcTokenStore是JDBC版本,存储token数据在一个关系数据库。使用JDBC版本你可以分享数据库在多个服务器之间,或者在相同的服务器之间进行扩展,或者多个资源和认证服务器。使用JsbcTokenStore必须要有“spring-jdbc"。

3.JSON Web Token(JWT)版本存储编码所有的有关授权的数据到token中(所以完全没有后端存储是优势),一个不利的是,你不能很简单的撤回一个access token ,所以他们正常情况下被授权短期时间和处理撤回使用刷新token。另一个不利的是,如果你存储很多的用户认证信息的话,tokens会很大。JwtTokenStore不是一个真实的存储,它不会固话任何数据,但是它在DefaultTokenServices中扮演了将token值和授权信息翻译成相同的值的角色。

JWT tokens

为了使用jwt tokens 你需要一个JWTTokenStore在你的认证服务器上。资源服务器也需要可以解码tokens,所以JWTAccessTokenConverter需要支持JWTTokenStore,并且认证服务器和资源服务器都需要实现它。Tokens默认的被声明,资源服务器需要能够校验签名,所以它也需要相同与认证服务器的对称KEY,或者他需要认证服务器上私钥对应的公钥。公钥在认证服务器的/oauth/token_key终端上被发布,它的默认保护权限是denyAll()。你可以在AuthorizationServerSecurityConfigurer中用标准的SpEL表达式开启它。(例如设置成permitAll())

使用JWTTokenStore需要在classpath中导入spring-security-jwt包。

Grant Type(授权类型)

授权终端支持的授权类型可以通过AuthorizationServerEndpointsConfigurer配置。默认情况下,所有的类型都被支持,除了password。下面的参数影响授权类型。

authenticationManager:通过注入一个authenticationManager授权类型被打开。

userDetailsService:如果你注入了一个userDetailsService或者以共有方式配置了一个userDetailsService(在
GlobalAuthenticationManagerConfigurer),那么一个刷新token权限将会包括一个user details检查,以确保这个用户是活动的。

authorizationCodeServices:为授权码权限定义一个授权码服务(AuthorizationCodeServices的实例)

imlpicitGrantService:在imlpicit授权过程中管理状态。

tokenGranter:TokenGranter(结果说有的授权控制,忽略说有的参数)

在XML授权类型包括了这些子节点在authorization-server中

配置终端的URL

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

默认(由框架实现)的终端URL地址

自定义必填地址(由"/"开始)

框架提供的URL地址是/oauth/authorize(授权终端),/oauth/token/(token 终端),/oauth/confirm_access(用户发送授权),/oauth/error(用来在认证服务器上渲染错误信息),/oauth/check_token(资源服务器用来解码access tokens)和/oauth/token_key(如果应用了JWT tokens,用来给token认证发布公钥)

授权终端/oauth/authorize需要被使用Spring Security保护起来,所以这个只能被授权用户访问。例如使用一个标准Spring Security WebSecurityConfigurer:

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

注意:如果你的授权服务器同时也是一个资源服务器,那么,这里会有另一个低优先级的安全过滤器链表控制API资源。这些请求会被利用 access token保护起来,你需要这些地址在主要的用户层面过滤器链表中不被配备。所以,确定包含一个请求匹配者,它只是排除WebSecurityConfigurer涵盖的non-API源。

对于你来说token终端默认被@Configuration支持的,使用HTTP基础认证的客户端密码的Spring OAuth保护,在XML配置中并不是这样(所以,它需要被显式的声明保护)

在XML配置中<authorization-server/>元素有一些按照相同的方式改变默认终端URL的参数。/check_token终端需要被显式的启用。(使用 check-token-enabled属性)

大部分的授权服务器终端被设备主要使用,但是这里有两三个源需要一个UI,他们是/oauth/confirm_access的GET和/oauth/error的HTML应答。他们在框架中被支持用白板页面实现,所以,说真的,大部分的授权服务器实现将会想他们自己提供页面,所以他们想控制页面风格和内容。所有这些你想的都可以使用SpringMVC的Controller实现,为这些终端使用@RequestMappings,默认情况下,在调度器中MVC框架采用低优先级。在/oauth/confirm_access终端,你可以预料到一个AuthorizationRequest绑定到了session,携带者所有从用户处搜索授权的数据(默认的实现是WhitelabelApprovalEndpoint),你可以从这个request中获取所有的数据,以你的方式渲染它,然后用户需要做的就是携带授权或者拒绝授权信息POST返回到/oauth/authorize。这里的请求参数会岂可发送给一个UserApprovalHandler在AuthorizationEndpoint中,所以你可以随意解释这个数据。默认的UserApprovalHandler依赖于你是否提供了一个approvalStore在你的AuthorizationServerEndpointsConfigurer中(在这种情况下,它是ApprovalStoreUserApprovalHandler)或者没有(这种情况下,它是TokenStoreUserApprovalHandler)。标准提供处理器接受一下两种:

TokenStoreUserApprovalHandler:一个简单的是否决定,通过user_oauth_approval等于TURE或FALSE

ApprovalStoreUserApprovalHandler:一个scope.*的集合,*等于请求开始的范围,参数可以死TRUE或者APPROVED(如果用户授予了授权)或者用户被认为被注入的那个范围。一个授权是否成功取决于最后的范围是否被授权。

注意:不要忘记包含CSRF在你给客户的表格里,默认情况下Spring Security预测一个叫“_csrf”的请求参数(并且在请求的属性中提供这个值),查看Spring Security用户文档获得更多的消息,或者参照whitelabel的实现。

执行SSL

简单的HTTP是非常好测试的,但是一个授权服务器应该在SSL使用的情况下部署在产品中。你能运行这个应用在一个安全的容器中或者通过一个代理,它会运
行的很好,如果你正确的设置了代理或者容器(这与OAuth2无关)。你也许也会利用Spring Security require requiresChannel()来保护终端。对于/authorize终端,你可以让他成为你正常安全应用的一部分。对于/token 终端,这有一个标志在AuthorizationServerEndpointsConfigurer中,你可以设置它使用sslOnly()方法。这两个安全通道的设置都是可选的,但是都将让Spring
Security重定向到安全通道,如果它发现了一个在非安全通道上的请求。

自定义错误处

授权服务器的错误处理使用标准的spring mvc特性,声明@ExceptionHandler方法在终端本身上上。用户也合一自己提供一个WebRespongseExceptionTranslator给终端,相比起给用户渲染,这是一个改变回复用户内容的好的方式。错误的渲染在token 终端中代表HttpMessageConverters(他可以被添加到MVC配置中)和在认证终端中的错误视图。白板的错误终端配HTML responses支持,但是用户也许需要提供一个自定义的实现。(例子:添加一个有@RequestMapping("/oauth/error")的@Controller)

映射用户权限到范围

有限时候限制tokens的范围不仅使用客户端分配的范围是很有用的,还要依照用户自己的权限。如果你使用一个DefaultOAuth2RequestFactory在你的AuthorizationEndpoint,你可以设置一个checkUserScopes=true来限制允许的范围只在用户权限范围之内。你也可以注入一个OAuth2RequestFactory在TokenEndpint中,但是它只会在你定义了TokenEndpointAuthenticationFilter之后才会有效--你只需要在HTTP
BasicAuthenticationFilter之后加入这个过滤器。AuthorizationServerEndpoingsConfigurer允许你注入一个自定义的OAuth2RequestFactory,所以你可以使用这个特性来设置一个工厂,如果你使用了@EnableAuthorizationServer

资源服务器的配置

一个资源服务器(可以和授权服务器是相同的或者不同的应用)为OAuth2 token保护的资源服务。

Spring OAuth 提供一个Spring Security授权过滤器,它实现这个保护。你可以开启它使用@EnableResourceServer在一个@Configuration类中,配置它使用一个ResourceServerConfigurer。下面的特性可以被配置:

TokenServices:这个bean定义了token服务(ResourceServerTokenServices的实例)

resourceId:资源的id(可选,但是推荐设置,他将被授权服务器验证,如果有的话)

其他的资源服务器的扩展节点(例如:从到来的请求里面获取tokens的tokenExtractor)

对于保护资源的请求匹配(默认是all)

保护资源的准入规则(默认是authenticated)

保护资源的通过Spring Security的HttpSecurity配置的其他自定义权限。

@EnableResourceServer注解自动加入一个OAuth2AuthenticationProcessingFilter类型的过滤器到Spring Security过滤链

在XML配置中,有<resource-server/>元素,有一个id参数,这个bean的id是一个servlet Filter,这个Filter可以手动的添加到标准的Spring Security链中。

你的ResourceServerTokenServices是一个认证服务器的另一半组成部分。如果你的认证服务和资源服务是相同的应用,而且你使用了
DefaultTokenServices,那么你不用想太多,因为它实现了所有必要的接口,所以它可以自动的保持一致。如果你的资源服务是一个分隔的系统,你必须确保你符合认证服务器的功能,还要提供一个ResourceServerTokenServices,它要知道如何正确解码tokens。与授权服务器一样,你可以进场使用DefaultTokenServices,大部分选择通过TokenStore来表示。另一个选择是RemoteTokenServices,它是一个Spring
OAuth的特性,允许资源服务器通过在认证服务器上的HTTP源(/oauth/check_token)解码tokens。RemoteTokenServices是实用的,如果在资源服务器上没有很大量的传输数据(每一个请求都在资源服务器上校验),或者,如果你可以给予缓存结果。使用/oauth/check_token断点你需要发布它,通过修改它的准入规则(默认是denyAll())在AuthorizationServerSecurityConfigurer中。

如下:

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

在这个例子中,我们可以配置/oauth/check_token终端和/oauth/token_key终端,他们两个终端都被HTTP Basic 授权使用客户端证书保护。

配置一个OAuth-aware表达式处理器

你可能想要获得一个Spring Security的基于表达式的入口控制的优势。在@EnableResourceServer步骤中会默认注册一个表达式处理器。这种表达式包括e#oauth2.clientHasRole,
#oauth2.clientHasAnyRole, and
#oath2.denyClient,它们用来支持基于用户权限规则的入口(参看在OAuth2SecurityExpressionMethods中的一个综合的列表),在XML配置中你可以使用expression-handler元素注册一个oauth-aware表达式处理器在<http/>安全配置中。

OAuth2.0客户端

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

受保护的资源配置

受保护的资源(或“远程资源”)可以定义使用OAuth2ProtectedResourceDetails类型的bean定义。受保护的资源具有以下属性:

id:资源的id。该id仅供客户端查找资源,在OAuth协议中从未使用过。它还被用作bean的id。

clientId:OAuth客户端id,这是OAuth提供者标识客户端的id。

clientSecret:与资源有关的密码。默认情况下,密码为空。

accessTokenUri:提供访问令牌的提供者OAuth端点的URI。

scope:逗号分割的字符串列表,指定访问资源的范围。默认情况下,没有指定范围。

clientAuthenticationScheme:这个方案被你的客户端使用,用来认证access token端点。建议值:“http_basic”和“form”。默认值:“http_basic”。见OAuth 2规范的第2.1节。

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

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

在XML <resource/ >元素,可以用于创建一个OAuth2ProtectedResourceDetails类型的bean。它具有匹配上面所有属性的属性。

对于OAuth2.0客户端,使用@EnableOauth2Client配置非常简单,它做了两件事:

1.建立一个过滤器bean(ID是oauth2ClientContextFilter)来存储当前的request和context。对于需要在请求中进行身份验证的情况,它管理重定向和OAuth认证URI。

2.在request 范围内建立一个AccessTokenRequest类型的bean。授权代码(或隐式)授权客户端可以使用此方法来保存与单个用户的冲突相关的状态。

过滤器必须配置到应用程序(例如,使用Servlet初始化器或web.xml中用一个DelegatingFilterProxy配置 。

可以在OAuth2RestTemplate中使用AccessTokenRequest,像下面这样:

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

OAuth2ClientContext在session范围内被放置,以保持不同用户状态,如果没有这些,你必须管理一个等效的数据结构在服务器上,映射请求到用户,并将每个用户与OAuth2ClientContext单独实例关联起来。

在XML中,有一个带有id属性的< client / >元素—这是一个servlet过滤器的bean id,它必须被映射到一个DelegatingFilterProxy (具有相同名称)的@ configuration示例中。

访问受保护的资源

一旦为资源提供了所有配置,现在就可以访问这些资源。访问这些资源的建议方法是使用Spring 3中引入的RestTemplate。OAuth的Spring Security提供了一个扩展创建RestTemplate只需要提供OAuth2ProtectedResourceDetails的实例。要使用用户令牌(授权代码授权),您应该考虑使用@ enableoauth2client配置(或XML等价< oauth:rest - template / >),创建一些请求和会话范围的上下文对象,以便不同用户的请求不会在运行时发生冲突。

作为一般规则,一个web应用不应该使用用户密码授权,所以如果你能同意使用AuthorizationCodeResourceDetails的话,避免使用ResourceOwnerPasswordResourceDetails 。如果你不要命的使用密码授权在一个java客户端上,那么使用相同的机制去配置你的OAuth2RestTemplate和添加证书到AccessTokenRequest(他是一个Map,并且是短暂的)而不是到ResourceOwnerPasswordResourceDetails(它是access
tokens中共享的)。

在客户端持久化令牌

一个客户端不需要持久化灵台,但是每次重启客户端的时候,用户不需要重新批准一个新的令牌是很好的。这个ClientTokenServices接口定义了为特定用户维护OAuth2.0令牌所需要的操作。提供了一个JDBC实现,但是如果你希望实现自己的服务来访问令牌和关联身份验证实例存储起来,那么你可以使用。如果你要使用此功能,则需要向OAuth2RestTemplate提供特殊配置的TokenProvider。

@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;

}

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

一些外部的OAuth2 提供者(例如facebook) 并不完全的实现规范,或者他们还在Spring Security OAuth的旧版本上。要在客户端应用程序中使用这些提供者,你可能需要调整客户端基础结构的各个部分。

以Facebook为例,在tonr2应用程序中有一个Facebook的特性(你需要更改配置来添加你自己的、有效的、客户的id和秘密——它们很容易在Facebook网站上生成)。

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

完。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  spring oauth2.0 SSO