OAuth2简介
参考微服务统⼀认证⽅案
OAuth 2.0是用于授权的行业标准协议。OAuth 2.0为简化客户端开发提供了特定的授权流,包括Web应用、桌面应用、移动端应用等。使用OAuth2 认证的好处就是你只需要一个账号密码,就能在各个网站进行访问,而面去了在每个网站都进行注册的繁琐过程,如:很多网站都可以使用微信登录,网站作为第三方服务、微信作为服务提供商.
OAuth2角色
- Resource owner(资源拥有者):拥有该资源的最终用户,他有访问资源的账号密码;
- Resource server(资源服务器):拥有受保护资源的服务器,如果请求包含正确的访问令牌,可以访问资源;
- Client(客户端):访问资源的客户端,会使用访问令牌去获取资源服务器的资源,可以是浏览器、移动设备或者服务器;
- Authorization server(授权服务器):用于认证用户的服务器,如果客户端认证通过,发放访问资源服务器的令牌。
授权模式
- Authorization Code(授权码模式):是功能最完整、流程最严密的授权模式,客户端先将用户导向认证服务器,登录后获取授权码,然后进行授权,最后根据授权码获取访问令牌;
- Resource Owner Password Credentials(密码模式):客户端直接向用户获取用户名和密码,之后向认证服务器获取访问令牌;
- Implicit(简化模式):和授权码模式相比,取消了获取授权码的过程,直接获取访问令牌;
- Client Credentials(客户端模式):客户端直接通过客户端认证(比如client_id和client_secret)从认证服务器获取访问令牌。
配置类AuthorizationServerConfigurerAdapter
@EnableAuthorizationServer //为微服务运行环境提供一个基于 OAuth2 协议的授权服务
public class config extends AuthorizationServerConfigurerAdapter {
@Override //用来配置令牌端点(Token Endpoint)的安全约束
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
super.configure(security);
}
@Override //配置客户端详情
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
super.configure(clients);
}
@Override //用来配置授权(authorization)以及令牌(token)的访问端点和令牌服务(token services)
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
super.configure(endpoints);
}
}
1. 配置客户端详情(Client Details)
能够使用内存或 JDBC 方式实现获取已注册的客户端详情,有几个重要的属性:
- withClient:客户端标识 ID
- secret:客户端安全码
- scope:客户端访问范围,默认为空则拥有全部范围
- authorizedGrantTypes:客户端使用的授权类型,默认为空
- authorities:客户端可使用的权限
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("admin-app")
.secret(passwordEncoder.encode("123456"))
.scopes("all")
.authorizedGrantTypes("password", "refresh_token")
.accessTokenValiditySeconds(3600*24)
.refreshTokenValiditySeconds(3600*24*7)
.and()
.withClient("portal-app")
.secret(passwordEncoder.encode("123456"))
.scopes("all")
.authorizedGrantTypes("password", "refresh_token")
.accessTokenValiditySeconds(3600*24)
.refreshTokenValiditySeconds(3600*24*7);
}
2. 配置令牌管理(EndpointsConfigurer)
JwtAccessTokenConverter是用来生成token的转换器,而token令牌默认是有签名的,且资源服务器需要验证这个签名。此处的加密及验签包括两种方式:对称加密、非对称加密(公钥密钥).对称加密需要授权服务器和资源服务器存储同一key值,而非对称加密可使用密钥加密,暴露公钥给资源服务器验签.
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
endpoints.authenticationManager(authenticationManager)
// 配置JwtAccessToken转换器
.accessTokenConverter(jwtAccessTokenConverter())
// refresh_token需要userDetailsService
.reuseRefreshTokens(false)
//配置加载用户信息的服务;
.userDetailsService(userDetailsService)
}
//使用非对称加密算法来对Token进行签名
@Bean
public JwtAccessTokenConverter jwtAccessTokenConverter() {
final JwtAccessTokenConverter converter = new JwtAccessToken();
// 导入证书
KeyStoreKeyFactory keyStoreKeyFactory =
new KeyStoreKeyFactory(new ClassPathResource("keystore.jks"), "mypass".toCharArray());
converter.setKeyPair(keyStoreKeyFactory.getKeyPair("mytest"));
return converter;
}
3. 配置安全规则(SecurityConfigurer)
@Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) {
oauthServer
// 开启/oauth/token_key验证端口无权限访问
.tokenKeyAccess("permitAll()")
// 开启/oauth/check_token验证端口认证权限访问
.checkTokenAccess("isAuthenticated()");
}
Q.E.D.