認證鑑權服務基於Spring Security 、Spring cloud Oauth2實現整個框架安全認證,提供統一權限認證受權及資源訪問服務解決方案,認證中心默認提供密碼模式(password),並支持原生 token 交互訪問業務。前端
OAuth2用戶是一個標準化的受權協議/框架,OAuth 2.0受權框架使第三方應用程序來獲取對HTTP服務的有限訪問機會。不管是經過編排資源全部者和HTTP服務之間的交互批准的資源全部者,或經過容許第三方應用程序來獲取本身的訪問權限。redis
(A)用戶打開客戶端之後,客戶端要求用戶給予受權。數據庫
(B)用戶贊成給予客戶端受權。json
(C)客戶端使用上一步得到的受權,向認證服務器申請令牌。緩存
(D)認證服務器對客戶端進行認證之後,確認無誤,贊成發放令牌。安全
(E)客戶端使用令牌,向資源服務器申請獲取資源。服務器
(F)資源服務器確認令牌無誤,贊成向客戶端開放資源。app
OAuth2.0認證步驟:框架
(A)用戶向客戶端提供用戶名和密碼。分佈式
(B)客戶端將用戶名和密碼發給認證服務器,向後者請求令牌。
(C)認證服務器確認無誤後,向客戶端提供訪問令牌。
客戶端請求發出的HTTP方式:
POST /token HTTP/1.1
Host: /auth/oauth/token
Authorization: Bearer czZCaGRSa3F0MzpnWDFmQmF0M2JW
Content-Type: application/x-www-form-urlencoded
grant_type=password&username=104573622026289&password=admin123
認證服務器返回認證消息:
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"
}
├── ui -- 前端工程 ├── framework-auth -- 認證、鑑權服務模塊
├── framework-common -- 公用模塊 ├ └── framework-common-cores -- 公共工具類核心包 ├ └── framework-common-security -- 安全工具類 ├ ├── framework-oauth -- 認證鑑權服務
├ ├──framework-system -- 組織機構權限服務
描述:咱們須要向這個類中, 配置用戶信息, 生成對應的AuthenticationManager, 同時做爲用戶身份的管理者,提供認證入口。
AuthorizationServerConfigurerAdapter介紹:
WebSecurityConfigurerAdapter介紹:
配置Security的認證策略,authorizeRequests()配置路徑攔截,代表路徑訪問所對應的權限,角色,認證信息。像WebSecurityConfigurerAdapter中配置用戶信息, 生成對應的AuthenticationManager做爲用戶身份的管理者;UserDetailsService用於獲取用戶的信息,本案例從數據庫獲取存到分佈式緩存中。
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers( "/token/**").permitAll()
.anyRequest().authenticated()
.and().csrf().disable();
}
2.OAuth2.0 暴露獲取令牌TokenEndpoint
/oauth/token:令牌端點
TokenEndpoint:用來做爲請求者得到令牌(Token)的服務,默認的路徑 /oauth/token,
定義受權和令牌端點以及令牌服務
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
endpoints
.allowedTokenEndpointRequestMethods(HttpMethod.GET, HttpMethod.POST)
.tokenStore(tokenStore())
.tokenEnhancer(tokenEnhancer())
.userDetailsService(userDetailsService)
.authenticationManager(authenticationManager)
.reuseRefreshTokens(false)
.exceptionTranslator(new CustomWebResponseExceptionTranslator());
}
3.認證中心服務容器監聽認證結果
ApplicationListener<AuthenticationSuccessEvent>、ApplicationListener<AbstractAuthenticationFailureEvent>
MerAuthenticationSuccessEventHandler 繼承 AuthenticationSuccessEvent處理成功返回認證、鑑權的結果。
public void handle(Authentication authentication) {
ClientDetails clientDetails = clientDetailsService.loadClientByClientId(StringConstnts.CLIENT_ID);
TokenRequest tokenRequest = new TokenRequest(new HashMap<>(), StringConstnts.CLIENT_ID, clientDetails.getScope(), "password");
OAuth2Request oAuth2Request = tokenRequest.createOAuth2Request(clientDetails);
OAuth2Authentication auth2Authentication = new OAuth2Authentication(oAuth2Request, authentication);
OAuth2AccessToken token = tokenStore.getAccessToken(auth2Authentication);
OAuth2AccessToken token1 = authorizationServerTokenServices.getAccessToken(auth2Authentication);
redisTemplate.opsForValue().set(token, authentication.getAuthorities());
log.info("用戶:{} 登陸成功", authentication.getPrincipal());
}
MerAuthenticationFailureEvenHandler 繼承 AbstractAuthenticationFailureEvent 認證失敗返回失敗消息體。
public void onApplicationEvent(AbstractAuthenticationFailureEvent event) { AuthenticationException authenticationException = event.getException(); Authentication authentication = (Authentication) event.getSource(); handle(authenticationException, authentication); }