假設咱們的accessToken是這樣的spring
{
"access_token": "ffb71ed0-5e48-44bc-b4aa-16ee0ba24b01",
"token_type": "bearer",
"refresh_token": "70220a36-3419-4c48-a60e-2d80b0f1774f",
"expires_in": 28799,
"scope": "app"
}安全
獲取當前用戶的Authentication,Authentication是一個接口,具體實現類是OAuth2Authentication,由如下返回結果可知,他是一個包含了大量信息的類.而每個信息塊裏面又有着接口和實現類.session
@GetMapping("/user-me") public Authentication principal() { Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); log.debug("user-me:{}", authentication.getName()); return authentication; }
請求http://127.0.0.1:50075/user-me?access_token=ffb71ed0-5e48-44bc-b4aa-16ee0ba24b01app
返回結果以下less
{
"authorities": [
{
"authority": "back:menu:set2role"
},
{
"authority": "mail:update"
},
{
"authority": "back:permission:delete"
},
{
"authority": "role:permission:byroleid"
},
{
"authority": "back:menu:save"
},
{
"authority": "back:menu:query"
},
{
"authority": "ip:black:query"
},
{
"authority": "ip:black:save"
},
{
"authority": "file:del"
},
{
"authority": "ip:black:delete"
},
{
"authority": "mail:query"
},
{
"authority": "back:user:query"
},
{
"authority": "back:role:permission:set"
},
{
"authority": "sms:query"
},
{
"authority": "back:role:query"
},
{
"authority": "back:permission:query"
},
{
"authority": "back:role:save"
},
{
"authority": "back:user:role:set"
},
{
"authority": "log:query"
},
{
"authority": "file:query"
},
{
"authority": "back:menu:update"
},
{
"authority": "back:role:update"
},
{
"authority": "back:role:delete"
},
{
"authority": "back:user:password"
},
{
"authority": "ROLE_SUPER_ADMIN"
},
{
"authority": "back:menu:delete"
},
{
"authority": "back:user:update"
},
{
"authority": "menu:byroleid"
},
{
"authority": "mail:save"
},
{
"authority": "user:role:byuid"
},
{
"authority": "back:permission:save"
},
{
"authority": "back:permission:update"
}
],
"details": {
"remoteAddress": "127.0.0.1",
"sessionId": null,
"tokenValue": "ffb71ed0-5e48-44bc-b4aa-16ee0ba24b01",
"tokenType": "Bearer",
"decodedDetails": null
},
"authenticated": true,
"userAuthentication": {
"authorities": [
{
"authority": "back:menu:set2role"
},
{
"authority": "mail:update"
},
{
"authority": "back:permission:delete"
},
{
"authority": "role:permission:byroleid"
},
{
"authority": "back:menu:save"
},
{
"authority": "back:menu:query"
},
{
"authority": "ip:black:query"
},
{
"authority": "ip:black:save"
},
{
"authority": "file:del"
},
{
"authority": "ip:black:delete"
},
{
"authority": "mail:query"
},
{
"authority": "back:user:query"
},
{
"authority": "back:role:permission:set"
},
{
"authority": "sms:query"
},
{
"authority": "back:role:query"
},
{
"authority": "back:permission:query"
},
{
"authority": "back:role:save"
},
{
"authority": "back:user:role:set"
},
{
"authority": "log:query"
},
{
"authority": "file:query"
},
{
"authority": "back:menu:update"
},
{
"authority": "back:role:update"
},
{
"authority": "back:role:delete"
},
{
"authority": "back:user:password"
},
{
"authority": "ROLE_SUPER_ADMIN"
},
{
"authority": "back:menu:delete"
},
{
"authority": "back:user:update"
},
{
"authority": "menu:byroleid"
},
{
"authority": "mail:save"
},
{
"authority": "user:role:byuid"
},
{
"authority": "back:permission:save"
},
{
"authority": "back:permission:update"
}
],
"details": {
"grant_type": "password",
"scope": "app",
"client_secret": "system",
"client_id": "system",
"username": "admin|USERNAME"
},
"authenticated": true,
"principal": {
"id": 1,
"username": "admin",
"password": "$2a$10$3uOoX1ps14CxuotogUoDreW8zXJOZB9XeGdrC/xDV36hhaE8Rn9HO",
"nickname": "測試1",
"headImgUrl": "",
"phone": "",
"sex": 1,
"enabled": true,
"type": "APP",
"createTime": "2018-01-17T16:56:59.000+0000",
"updateTime": "2018-01-17T16:57:01.000+0000",
"sysRoles": [
{
"id": 1,
"code": "SUPER_ADMIN",
"name": "超級管理員",
"createTime": "2018-01-19T20:32:16.000+0000",
"updateTime": "2018-01-19T20:32:18.000+0000"
}
],
"permissions": [
"back:menu:set2role",
"mail:update",
"back:permission:delete",
"role:permission:byroleid",
"back:menu:save",
"back:menu:query",
"ip:black:query",
"ip:black:save",
"file:del",
"ip:black:delete",
"mail:query",
"back:user:query",
"back:role:permission:set",
"sms:query",
"back:role:query",
"back:permission:query",
"back:role:save",
"back:user:role:set",
"log:query",
"file:query",
"back:menu:update",
"back:role:update",
"back:role:delete",
"back:user:password",
"back:menu:delete",
"back:user:update",
"menu:byroleid",
"mail:save",
"user:role:byuid",
"back:permission:save",
"back:permission:update"
],
"credentialsNonExpired": true,
"accountNonExpired": true,
"accountNonLocked": true
},
"credentials": null,
"name": "admin"
},
"credentials": "",
"principal": {
"id": 1,
"username": "admin",
"password": "$2a$10$3uOoX1ps14CxuotogUoDreW8zXJOZB9XeGdrC/xDV36hhaE8Rn9HO",
"nickname": "測試1",
"headImgUrl": "",
"phone": "",
"sex": 1,
"enabled": true,
"type": "APP",
"createTime": "2018-01-17T16:56:59.000+0000",
"updateTime": "2018-01-17T16:57:01.000+0000",
"sysRoles": [
{
"id": 1,
"code": "SUPER_ADMIN",
"name": "超級管理員",
"createTime": "2018-01-19T20:32:16.000+0000",
"updateTime": "2018-01-19T20:32:18.000+0000"
}
],
"permissions": [
"back:menu:set2role",
"mail:update",
"back:permission:delete",
"role:permission:byroleid",
"back:menu:save",
"back:menu:query",
"ip:black:query",
"ip:black:save",
"file:del",
"ip:black:delete",
"mail:query",
"back:user:query",
"back:role:permission:set",
"sms:query",
"back:role:query",
"back:permission:query",
"back:role:save",
"back:user:role:set",
"log:query",
"file:query",
"back:menu:update",
"back:role:update",
"back:role:delete",
"back:user:password",
"back:menu:delete",
"back:user:update",
"menu:byroleid",
"mail:save",
"user:role:byuid",
"back:permission:save",
"back:permission:update"
],
"credentialsNonExpired": true,
"accountNonExpired": true,
"accountNonLocked": true
},
"clientOnly": false,
"oauth2Request": {
"clientId": "system",
"scope": [
"app"
],
"requestParameters": {
"grant_type": "password",
"scope": "app",
"client_id": "system",
"username": "admin|USERNAME"
},
"resourceIds": [],
"authorities": [],
"approved": true,
"refresh": false,
"redirectUri": null,
"responseTypes": [],
"extensions": {},
"grantType": "password",
"refreshTokenRequest": null
},
"name": "admin"
}ide
首先咱們須要寫一個資源配置類測試
@Configuration @EnableResourceServer public class ResourceServerConfig extends ResourceServerConfigurerAdapter
其中這個@EnableResourceServer實際上幫咱們加入了一個過濾器(應該說全部的業務模塊都要有一個資源配置類來開啓這個過濾器)org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationProcessingFilterui
在他的源碼中有一個doFilterthis
public class OAuth2AuthenticationProcessingFilter implements Filter, InitializingBean
private TokenExtractor tokenExtractor = new BearerTokenExtractor();
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { boolean debug = logger.isDebugEnabled(); HttpServletRequest request = (HttpServletRequest)req; HttpServletResponse response = (HttpServletResponse)res; try { //從request中解析PreAuthenticatedAuthenticationToken(注意這裏並非OAuth2Authentication) Authentication authentication = this.tokenExtractor.extract(request); if(authentication == null) { if(this.stateless && this.isAuthenticated()) { if(debug) { logger.debug("Clearing security context."); } SecurityContextHolder.clearContext(); } if(debug) { logger.debug("No token in request, will continue chain."); } } else { request.setAttribute(OAuth2AuthenticationDetails.ACCESS_TOKEN_VALUE, authentication.getPrincipal()); if(authentication instanceof AbstractAuthenticationToken) { AbstractAuthenticationToken needsDetails = (AbstractAuthenticationToken)authentication; needsDetails.setDetails(this.authenticationDetailsSource.buildDetails(request)); } Authentication authResult = this.authenticationManager.authenticate(authentication); if(debug) { logger.debug("Authentication success: " + authResult); } this.eventPublisher.publishAuthenticationSuccess(authResult); //此處爲把authResult放入安全容器中,此處比較重要 SecurityContextHolder.getContext().setAuthentication(authResult); } } catch (OAuth2Exception var9) { SecurityContextHolder.clearContext(); if(debug) { logger.debug("Authentication request failed: " + var9); } this.eventPublisher.publishAuthenticationFailure(new BadCredentialsException(var9.getMessage(), var9), new PreAuthenticatedAuthenticationToken("access-token", "N/A")); this.authenticationEntryPoint.commence(request, response, new InsufficientAuthenticationException(var9.getMessage(), var9)); return; } chain.doFilter(request, response); }
TokenExtractor也是一個接口,咱們能夠看到,他是由BearerTokenExtractor實現類來實現的.基本上BearerTokenExtractor整個對象的方法都有調用.debug
public class BearerTokenExtractor implements TokenExtractor { private static final Log logger = LogFactory.getLog(BearerTokenExtractor.class); public BearerTokenExtractor() { } public Authentication extract(HttpServletRequest request) { String tokenValue = this.extractToken(request); if(tokenValue != null) { PreAuthenticatedAuthenticationToken authentication = new PreAuthenticatedAuthenticationToken(tokenValue, ""); return authentication; } else { return null; } } /** *從request參數查找認證 */ protected String extractToken(HttpServletRequest request) { String token = this.extractHeaderToken(request); if(token == null) { logger.debug("Token not found in headers. Trying request parameters."); token = request.getParameter("access_token"); if(token == null) { logger.debug("Token not found in request parameters. Not an OAuth2 request."); } else { request.setAttribute(OAuth2AuthenticationDetails.ACCESS_TOKEN_TYPE, "Bearer"); } } return token; } /** *從request的header開始查找認證 */ protected String extractHeaderToken(HttpServletRequest request) { Enumeration headers = request.getHeaders("Authorization"); String value; do { if(!headers.hasMoreElements()) { return null; } value = (String)headers.nextElement(); } while(!value.toLowerCase().startsWith("Bearer".toLowerCase())); String authHeaderValue = value.substring("Bearer".length()).trim(); request.setAttribute(OAuth2AuthenticationDetails.ACCESS_TOKEN_TYPE, value.substring(0, "Bearer".length()).trim()); int commaIndex = authHeaderValue.indexOf(44); if(commaIndex > 0) { authHeaderValue = authHeaderValue.substring(0, commaIndex); } return authHeaderValue; } }
SecurityContextHolder.getContext().setAuthentication(authResult);咱們單獨把這個提取出來,在以前的
@GetMapping("/user-me") public Authentication principal() { Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); log.debug("user-me:{}", authentication.getName()); return authentication; }
咱們能夠看到咱們訪問的登陸驗證用戶是從SecurityContextHolder.getContext().getAuthentication()提取出來的.