auth2四种模式
第一种授权模式,指的是第三方应用先申请一个授权码,然后再用该码获取令牌。
通过https://b.com/oauth/authorize?response_type=code&
client_id=CLIENT_ID&redirect_uri=CALLBACK_URL&scope=read
然后跳转到 CALLBACK_URL?code=AUTHORIZATION_CODE
然后请求 /oauth/token?client_id=CLIENT_ID&
client_secret=CLIENT_SECRET&
grant_type=authorization_code&
code=AUTHORIZATION_CODE&
redirect_uri=CALLBACK_URL
CALLBACK_URL是回调回去的地址
第二种隐藏模式,许直接向前端颁发令牌。这种方式没有授权码这个中间步骤,所以称为(授权码)“隐藏式”(implicit)。
第三种密码模式,允许用户把用户名和密码,直接告诉该应用。该应用就使用你的密码,申请令牌,这种方式称为"密码式"(password)。就是直接用密码获取令牌。
第四种凭证式,用于没有前端的命令行应用,即在命令行下请求令牌。
例如https://oauth.b.com/token? grant_type=client_credentials&
client_id=CLIENT_ID& client_secret=CLIENT_SECRET
关键名词
(1) Third-party application:第三方应用程序,
(2)HTTP service:HTTP服务提供商,本文中简称"服务提供商",
(3)Resource Owner:资源所有者
(4)User Agent:用户代理,本文中就是指浏览器。
(5)Authorization server:认证服务器,即服务提供商专门用来处理认证的服务器
(6)Resource server:资源服务器,即服务提供商存放用户生成的资源的服务器。它与认证服务器,可以是同一台服务器,也可以是不同的服务器。
(A)客户端向资源所有者请求授权。授权请求可以直接对资源所有者(如图所示)进行,或者通过授权服务器作为中介进行间接访问(首选方案)。
(B)资源所有者允许授权,并返回凭证(如code)。
(C)客户端通过授权服务器进行身份验证,并提供授权凭证(如code),请求访问令牌(access token)。
(D)授权服务器对客户端进行身份验证,并验证授权凭证,如果有效,则发出访问令牌。
(E)客户端向资源服务器请求受保护的资源,并通过提供访问令牌来进行身份验证。
(F)资源服务器验证访问令牌,如果正确则返回受保护资源。
授权
授权码模式的实现
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
/**
* 注入authenticationManager 来支持 password grant type
*/
@Autowired
private AuthenticationManager authenticationManager;
@Resource
private UserDetailsService userDetailsService;
@Autowired
private TokenStore tokenStore;
@Autowired
private WebResponseExceptionTranslator webResponseExceptionTranslator;
@Autowired
private RedisClientDetailsService clientDetailsService;
@Autowired
private RandomValueAuthorizationCodeServices authorizationCodeServices;
@Autowired
private TokenGranter tokenGranter;
/**
* 配置身份认证器,配置认证方式,TokenStore,TokenGranter,OAuth2RequestFactory
* @param endpoints
*/
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
//配置token存储,一般配置redis存储
endpoints.tokenStore(tokenStore)
//配置认证管理器
.authenticationManager(authenticationManager)
//配置用户详情server,密码模式必须
.userDetailsService(userDetailsService)
//配置授权码模式授权码服务,不配置默认为内存模式
.authorizationCodeServices(authorizationCodeServices)
//为了定制spring -oauth的异常处理程序你必须定义的实例WebResponseExceptionTranslator :
.exceptionTranslator(webResponseExceptionTranslator)
//配置grant_type模式,如果不配置则默认使用密码模式、简化模式、验证码模式以及刷新token模式,如果配置了只使用配置中,默认配置失效
//具体可以查询AuthorizationServerEndpointsConfigurer中的getDefaultTokenGranters方法
.tokenGranter(tokenGranter);
}
/**
* 配置应用名称 应用id
* 配置OAuth2的客户端相关信息
* @param clients
* @throws Exception
*/
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.withClientDetails(clientDetailsService);
clientDetailsService.loadAllClientToCache();
}
/**
* 对应于配置AuthorizationServer安全认证的相关信息,创建ClientCredentialsTokenEndpointFilter核心过滤器
* @param security
*/
@Override
public void configure(AuthorizationServerSecurityConfigurer security) {
security
.tokenKeyAccess("isAuthenticated()")
.checkTokenAccess("permitAll()")
//让/oauth/token支持client_id以及client_secret作登录认证
.allowFormAuthenticationForClients();
}
}
继承这个适配器
ClientDetailsServiceConfigurer:用来配置客户端详情服务(ClientDetailsService),客户端详情信息在这里进行初始化,这里是通过数据库来存储(具体JdbcClientDetailsService已经帮我们实现,如需要改的需要扩展这个类),然后通过redis调取详情信息。
AuthorizationServerSecurityConfigurer:用来配置令牌端点(Token Endpoint)的安全约束.
AuthorizationServerEndpointsConfigurer:用来配置授权(authorization)以及令牌(token)的访问端点和令牌服务(token services)。
clientId - (必需)客户端ID。
secret - (可信客户端所需)客户端密钥(可选)。
scope - 客户受限的范围。如果范围未定义或为空(默认值),则客户端不受范围限制。
authorizedGrantTypes - 授权客户端使用的授权类型。默认值为空。
authorities - 授予客户的权限(常规Spring Security权限)。
redirectUris - 将用户代理重定向到客户端的重定向端点。它必须是绝对URL。
security
.tokenKeyAccess(“isAuthenticated()”)
.checkTokenAccess(“permitAll()”)
//让/oauth/token支持client_id以及client_secret作登录认证
.allowFormAuthenticationForClients();
这个东西就是Spring Security OAuth公开了两个用于检查令牌的端点( /oauth/check_token和 /oauth/token_key).默认情况下不会公开这些端点(具有访问权限“denyAll()”).
因此,如果您要使用此端点验证令牌,则必须将此添加到授权服务器的配置中
AuthorizationServerEndpointsConfigurer这个东东,往Spring容器中托管各个Endpoint(如用于处理/oauth/token请求的TokenEndpoint、用于处理/oauth/authorize请求的AuthorizationEndpoint等;
Endpoint可以看成是控制器。
资源服务器
public class DefaultResourceServerConf extends ResourceServerConfigurerAdapter {
@Autowired
private TokenStore tokenStore;
@Resource
private AuthenticationEntryPoint authenticationEntryPoint;
@Resource
private OAuth2WebSecurityExpressionHandler expressionHandler;
@Resource
private OAuth2AccessDeniedHandler oAuth2AccessDeniedHandler;
@Autowired
private SecurityProperties securityProperties;
@Override
public void configure(ResourceServerSecurityConfigurer resources) {
resources.tokenStore(tokenStore)
.stateless(true)
.authenticationEntryPoint(authenticationEntryPoint)
.expressionHandler(expressionHandler)
.accessDeniedHandler(oAuth2AccessDeniedHandler);
}
@Override
public void configure(HttpSecurity http) throws Exception {
ExpressionUrlAuthorizationConfigurer<HttpSecurity>.AuthorizedUrl authorizedUrl = setHttp(http)
.authorizeRequests()
.antMatchers(securityProperties.getIgnore().getUrls()).permitAll()
.antMatchers(HttpMethod.OPTIONS).permitAll()
.anyRequest();
setAuthenticate(authorizedUrl);
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
.and()
.httpBasic().disable()
.headers()
.frameOptions().disable()
.and()
.csrf().disable();
}
/**
* url权限控制,默认是认证就通过,可以重写实现个性化
* @param authorizedUrl
*/
public HttpSecurity setAuthenticate(ExpressionUrlAuthorizationConfigurer<HttpSecurity>.AuthorizedUrl authorizedUrl) {
return authorizedUrl.authenticated().and();
}
/**
* 留给子类重写扩展功能
* @param http
*/
public HttpSecurity setHttp(HttpSecurity http) {
return http;
}
}