《SpringSecurityOauth2原始碼分析》1.SpringSecurityOauth2原始碼分析之單點登陸SSO
阿新 • • 發佈:2018-12-16
OAuth2ClientContextFilter
處理UserRedirectRequiredException異常,做瀏覽器跳轉。當用戶跳轉到本地login時,如果發現UserRedirectRequiredException異常,跳轉認證中心 oauth/authorize介面,傳引數response_type,client_id,redirect_uri,scope。 (很熟悉吧)
認證中心發現未登入轉到登陸頁面。 登陸完之後會跳轉redirect_uri對應頁面(客戶端登入APi),這個請求帶code引數的,
然後走過濾器鏈,發現OAuth2ClientAuthenticationProcessingFilter認證通過了。 轉向快取的請求( 就是ExceptionTranslationFilter裡面的requestCache.saveRequest(request, response);)。
OAuth2ClientAuthenticationProcessingFilter
繼承AbstractAuthenticationProcessingFilter實現attemptAuthentication方法。和UsernamePasswordFilter是一類。
//在OAuth2ClientAuthenticationProcessingFilter中 @Override public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException { OAuth2AccessToken accessToken; try { accessToken = restTemplate.getAccessToken(); } catch (OAuth2Exception e) { BadCredentialsException bad = new BadCredentialsException("Could not obtain access token", e); publish(new OAuth2AuthenticationFailureEvent(bad)); throw bad; } try { OAuth2Authentication result = tokenServices.loadAuthentication(accessToken.getValue()); if (authenticationDetailsSource!=null) { request.setAttribute(OAuth2AuthenticationDetails.ACCESS_TOKEN_VALUE, accessToken.getValue()); request.setAttribute(OAuth2AuthenticationDetails.ACCESS_TOKEN_TYPE, accessToken.getTokenType()); result.setDetails(authenticationDetailsSource.buildDetails(request)); } publish(new AuthenticationSuccessEvent(result)); return result; } catch (InvalidTokenException e) { BadCredentialsException bad = new BadCredentialsException("Could not obtain user details from token", e); publish(new OAuth2AuthenticationFailureEvent(bad)); throw bad; } }
accessToken = restTemplate.getAccessToken(); 訪問認證伺服器獲取token的方法。 如果發現沒有code丟擲UserRedirectRequiredException異常。 如果獲取成功,那就離登入成功不遠了。
//在AuthorizationCodeAccessTokenProvider中 public String obtainAuthorizationCode(OAuth2ProtectedResourceDetails details, AccessTokenRequest request) throws UserRedirectRequiredException, UserApprovalRequiredException, AccessDeniedException, OAuth2AccessDeniedException { AuthorizationCodeResourceDetails resource = (AuthorizationCodeResourceDetails) details; HttpHeaders headers = getHeadersForAuthorizationRequest(request); MultiValueMap<String, String> form = new LinkedMultiValueMap<String, String>(); if (request.containsKey(OAuth2Utils.USER_OAUTH_APPROVAL)) { form.set(OAuth2Utils.USER_OAUTH_APPROVAL, request.getFirst(OAuth2Utils.USER_OAUTH_APPROVAL)); for (String scope : details.getScope()) { form.set(scopePrefix + scope, request.getFirst(OAuth2Utils.USER_OAUTH_APPROVAL)); } } else { form.putAll(getParametersForAuthorizeRequest(resource, request)); } authorizationRequestEnhancer.enhance(request, resource, form, headers); final AccessTokenRequest copy = request; final ResponseExtractor<ResponseEntity<Void>> delegate = getAuthorizationResponseExtractor(); ResponseExtractor<ResponseEntity<Void>> extractor = new ResponseExtractor<ResponseEntity<Void>>() { @Override public ResponseEntity<Void> extractData(ClientHttpResponse response) throws IOException { if (response.getHeaders().containsKey("Set-Cookie")) { copy.setCookie(response.getHeaders().getFirst("Set-Cookie")); } return delegate.extractData(response); } }; // Instead of using restTemplate.exchange we use an explicit response extractor here so it can be overridden by // subclasses ResponseEntity<Void> response = getRestTemplate().execute(resource.getUserAuthorizationUri(), HttpMethod.POST, getRequestCallback(resource, form, headers), extractor, form.toSingleValueMap()); if (response.getStatusCode() == HttpStatus.OK) { // Need to re-submit with approval... throw getUserApprovalSignal(resource, request); } URI location = response.getHeaders().getLocation(); String query = location.getQuery(); Map<String, String> map = OAuth2Utils.extractMap(query); if (map.containsKey("state")) { request.setStateKey(map.get("state")); if (request.getPreservedState() == null) { String redirectUri = resource.getRedirectUri(request); if (redirectUri != null) { request.setPreservedState(redirectUri); } else { request.setPreservedState(new Object()); } } } String code = map.get("code"); if (code == null) { throw new UserRedirectRequiredException(location.toString(), form.toSingleValueMap()); } request.set("code", code); return code; }