1 Oauth2.0
OAauth2.0包括以下角色:
1、客户端
本身不存储资源,需要通过资源拥有者的授权去请求资源服务器的资源,比如:Android客户端、Web客户端(浏览器端)、微信客户端等。
2、资源拥有者
通常为用户,也可以是应用程序,即该资源的拥有者。
3、授权服务器(也称认证服务器)
用于服务提供商对资源拥有的身份进行认证、对访问资源进行授权,认证成功后会给客户端发放令(access_token),作为客户端访问资源服务器的凭据。本例为微信的认证服务器。
4、资源服务器
存储资源的服务器,本例子为微信存储的用户信息。
现在还有一个问题,服务提供商能允许随便一个客户端就接入到它的授权服务器吗?答案是否定的,服务提供商会给准入的接入方一个身份,用于接入时的凭据:
client_id:客户端标识
client_secret:客户端秘钥
因此,准确来说,授权服务器对两种OAuth2.0中的两个角色进行认证授权,分别是资源拥有者、客户端
2.服务介绍
2.1 授权服务
配置流程
配置
1.客户端详情
2.令牌访问端点
包括令牌服务(tokensotre 和 DefaultTokenServices)
和令牌访问端点服务 需要 认证管理器、令牌管理服务、授权码服务等)
3.配置令牌端点的约束
授权服务 (Authorization Server)应包含对接入端以及登入用户的合法性进行验证并颁发token等功能,对令牌的请求端点由 Spring MVC 控制器进行实现,下面是配置一个认证服务必须要实现的endpoints
- AuthorizationEndpoint 服务于认证请求。默认 URL: /oauth/authorize 。
- TokenEndpoint 服务于访问令牌的请求。默认 URL: /oauth/token 。
- 资源服务 (Resource Server),应包含对资源的保护功能,对非法请求进行拦截,对请求中token进行解析鉴权等,下面的过滤器用于实现 OAuth 2.0 资源服务:
- OAuth2AuthenticationProcessingFilter 用来对请求给出的身份令牌解析鉴权。
public class AuthorizationServerConfigurerAdapter implements AuthorizationServerConfigurer {
public AuthorizationServerConfigurerAdapter() {}
/** 3.
配置令牌端点的访问约束 因为暴露了令牌的访问端点(url),什么样的情况下
运行访问url
类似于之前的 "/r/***".authenticated();所有/r/**必须要认证
*/
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {}
/**1.
客户端详情 客户端申请令牌,这个方法 负责出检查结果,是不是已经在
认证服务中已经配置的客户端。 可以查询数据库比较
*/
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {}
/** 2.
申请令牌(token)的访问端点, 也就是url
令牌如何申请管理 配置令牌服务 tokenService
*/
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {}
}
- ClientDetailsServiceConfigurer :用来配置客户端详情服务(ClientDetailsService),客户端详情信息在
这里进行初始化,你能够把客户端详情信息写死在这里或者是通过数据库来存储调取详情信息。 - AuthorizationServerEndpointsConfigurer :用来配置令牌(token)的访问端点和令牌服务(tokenservices)。
- AuthorizationServerSecurityConfigurer :用来配置令牌端点的安全约束.
2.1.1 配置客户端详情
2.1.2 配置令牌访问端点和令牌服务
2.1.2.1 管理令牌 tokenstore
AuthorizationServerTokenServices 接口定义了一些操作使得你可以对令牌进行一些必要的管理,令牌可以被用来加载身份信息,里面包含了这个令牌的相关权限。
管理令牌
- InMemoryTokenStore:
- JdbcTokenStore :这是一个基于JDBC的实现版本,令牌会被保存进关系型数据库。使用这个版本的实现时,你可以在不同的服务器之间共享令牌信息,使用这个版本的时候请注意把"spring-jdbc"这个依赖加入到你的classpath当中。
- JwtTokenStore :这个版本的全称是 JSON Web Token(JWT),它可以把令牌相关的数据进行编码(因此对于后端服务来说,它不需要进行存储,这将是一个重大优势),但是它有一个缺点,那就是撤销一个已经授权令牌将会非常困难,所以它通常用来处理一个生命周期较短的令牌以及撤销刷新令牌(refresh_token)。
另外一个缺点就是这个令牌占用的空间会比较大,如果你加入了比较多用户凭证信息。JwtTokenStore 不会保存任何数据,但是它在转换令牌值以及授权信息方面与 DefaultTokenServices 所扮演的角色是一样的。
@Configuration
public class TokenConfig {
@Bean
public TokenStore tokenStore() {
return new InMemoryTokenStore();
}
}
2.1.2.2 配置令牌服务
自己可以创建 AuthorizationServerTokenServices 这个接口的实现,则需要继承 DefaultTokenServices 这个类,里面包含了一些有用实现,你可以使用它来修改令牌的格式和令牌的存储。
@Autowired
private TokenStore tokenStore;
@Autowired
private ClientDetailsService clientDetailsService;
@Bean
public AuthorizationServerTokenServices tokenService() {
DefaultTokenServices service=new DefaultTokenServices();
service.setClientDetailsService(clientDetailsService);
service.setSupportRefreshToken(true);
service.setTokenStore(tokenStore);
service.setAccessTokenValiditySeconds(7200); // 令牌默认有效期2小时
service.setRefreshTokenValiditySeconds(259200); // 刷新令牌默认有效期3天
return service;
}
2.1.2.3 令牌访问端点配置
AuthorizationServerEndpointsConfigurer 这个对象的实例可以完成令牌服务以及令牌endpoint配置。
配置授权类型(Grant Types)
AuthorizationServerEndpointsConfigurer 通过设定以下属性决定支持的授权类型(Grant Types):
- authenticationManager :认证管理器,当你选择了资源所有者密码(password)授权类型的时候,请设置这个属性注入一个AuthenticationManager 对象。=((密码模式)
- userDetailsService :如果你设置了这个属性的话,那说明你有一个自己的 UserDetailsService 接口的实现,或者你可以把这个东西设置到全局域上面去(例如 GlobalAuthenticationManagerConfigurer 这个配置对象),当你设置了这个之后,那么 “refresh_token” 即刷新令牌授权类型模式的流程中就会包含一个检查,用来确保这个账号是否仍然有效,假如说你禁用了这个账户的话。 (密码模式)
- authorizationCodeServices 这个属性是用来设置授权码服务的(即 AuthorizationCodeServices 的实例对象),主要用于 “authorization_code” 授权码类型模式。
配置令牌访问端点
配置认证管理器
在webSecurityConfigurerAdapter 中配置
@Autowired
private AuthorizationCodeServices authorizationCodeServices;
@Autowired
private AuthenticationManager authenticationManager;
/**
令牌访问端点
*/
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
endpoints
// 认证服务器 在 在webSecurityConfigurerAdapter 中配置
.authenticationManager(authenticationManager)
//授权码模式
.authorizationCodeServices(authorizationCodeServices)
//在配置令牌服务中的tokenstore 和tokenservice
.tokenServices(tokenService())
.allowedTokenEndpointRequestMethods(HttpMethod.POST);
}
@Bean
public AuthorizationCodeServices authorizationCodeServices() { //设置授权码模式的授权码如何
//存取,暂时采用内存方式
return new InMemoryAuthorizationCodeServices();
}
2.1.3 配置令牌端点的安全约束
AuthorizationServerSecurityConfigurer :用来配置令牌端点(Token Endpoint)的安全约束,在AuthorizationServer中配置如下
@Override
public void configure(AuthorizationServerSecurityConfigurer security){
security
///oauth/token_key :提供公有密匙的端点,如果你使用JWT令牌的话。
.tokenKeyAccess("permitAll()") (1)
///oauth/check_token :用于资源服务访问的令牌解析端点
.checkTokenAccess("permitAll()") (2)
//可以表单认证 申请令牌
.allowFormAuthenticationForClients() (3)
;
}
2.2 授权码模式
3. 资源服务
@EnableResourceServer 注解到一个 @Configuration 配置类上,并且必须使用 ResourceServerConfigurer 这个配置对象来进行配置(可以选择继承自 ResourceServerConfigurerAdapter 然后覆写其中的方法,参数就是这个对象的实例),下面是一些可以配置的属性
ResourceServerSecurityConfigurer中主要包括
@Configuration
@EnableResourceServer
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class ResouceServerConfig extends
ResourceServerConfigurerAdapter {
public static final String RESOURCE_ID = "res1";
@Override
public void configure(ResourceServerSecurityConfigurer resources) {
resources.resourceId(RESOURCE_ID)//资源 id
// 自己验证 校验token 解析
.tokenStore(tokenStore)
// .tokenServices(tokenService())//验证令牌的服务
.stateless(true);
}
/*
此方法和web security 差不多
**/
@Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
// 所有访问 需要scope =all 才行
.antMatchers("/**").access("#oauth2.hasScope('all')")
.and().csrf().disable()
.sessionManagement()
//session 关闭SessionCreationPolicy.STATELESS
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
}