當(dāng)前位置:
首頁(yè) >
前端技术
> javascript
>内容正文
javascript
Spring Security OAuth2源码解析(二)
生活随笔
收集整理的這篇文章主要介紹了
Spring Security OAuth2源码解析(二)
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
鑒權(quán)服務(wù)器對(duì)客戶(hù)端鑒權(quán)之后,會(huì)生成token,客戶(hù)端使用token,就可以去資源服務(wù)器獲取資源。
@EnableResourceServer?
@Import(ResourceServerConfiguration.class) public @interface EnableResourceServer {}ResourceServerConfiguration
ResourceServerConfiguration是WebSecurityConfigurerAdapter的子類(lèi)實(shí)現(xiàn)。引入了ResourceServerSecurityConfigurer和ResourceServerTokenServices。
@Overrideprotected void configure(HttpSecurity http) throws Exception {//引入Filter配置ResourceServerSecurityConfigurer resources = new ResourceServerSecurityConfigurer();//引入ResourceServerTokenServicesResourceServerTokenServices services = resolveTokenServices();if (services != null) {resources.tokenServices(services);}else {if (tokenStore != null) {resources.tokenStore(tokenStore);}else if (endpoints != null) {resources.tokenStore(endpoints.getEndpointsConfigurer().getTokenStore());}}if (eventPublisher != null) {resources.eventPublisher(eventPublisher);}for (ResourceServerConfigurer configurer : configurers) {configurer.configure(resources);}//匿名驗(yàn)證,http.authenticationProvider(new AnonymousAuthenticationProvider("default"))// 異常處理.exceptionHandling().accessDeniedHandler(resources.getAccessDeniedHandler()).and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().csrf().disable();//filter chainhttp.apply(resources);if (endpoints != null) {// Assume we are in an Authorization Serverhttp.requestMatcher(new NotOAuthRequestMatcher(endpoints.oauth2EndpointHandlerMapping()));}for (ResourceServerConfigurer configurer : configurers) {// Delegates can add authorizeRequests() hereconfigurer.configure(http);}if (configurers.isEmpty()) {//所有請(qǐng)求需授權(quán)http.authorizeRequests().anyRequest().authenticated();}}ResourceServerSecurityConfigurer
ResourceServerSecurityConfigurer配置了:OAuth2AuthenticationProcessingFilter
@Overridepublic void configure(HttpSecurity http) throws Exception {//如果是OAuth2AuthenticationManager,則設(shè)置tokenService等。AuthenticationManager oauthAuthenticationManager = oauthAuthenticationManager(http);resourcesServerFilter = new OAuth2AuthenticationProcessingFilter();resourcesServerFilter.setAuthenticationEntryPoint(authenticationEntryPoint);resourcesServerFilter.setAuthenticationManager(oauthAuthenticationManager);if (eventPublisher != null) {resourcesServerFilter.setAuthenticationEventPublisher(eventPublisher);}if (tokenExtractor != null) {resourcesServerFilter.setTokenExtractor(tokenExtractor);}if (authenticationDetailsSource != null) {resourcesServerFilter.setAuthenticationDetailsSource(authenticationDetailsSource);}resourcesServerFilter = postProcess(resourcesServerFilter);resourcesServerFilter.setStateless(stateless);// @formatter:offhttp.authorizeRequests().expressionHandler(expressionHandler).and()//把OAuth2AuthenticationProcessingFilter 放在 AbstractPreAuthenticatedProcessingFilter 之前。.addFilterBefore(resourcesServerFilter, AbstractPreAuthenticatedProcessingFilter.class).exceptionHandling().accessDeniedHandler(accessDeniedHandler).authenticationEntryPoint(authenticationEntryPoint);// @formatter:on}?OAuth2AuthenticationManager?
private AuthenticationManager oauthAuthenticationManager(HttpSecurity http) {OAuth2AuthenticationManager oauthAuthenticationManager = new OAuth2AuthenticationManager();if (authenticationManager != null) {if (authenticationManager instanceof OAuth2AuthenticationManager) {oauthAuthenticationManager = (OAuth2AuthenticationManager) authenticationManager;}else {return authenticationManager;}}oauthAuthenticationManager.setResourceId(resourceId);oauthAuthenticationManager.setTokenServices(resourceTokenServices(http));oauthAuthenticationManager.setClientDetailsService(clientDetails());return oauthAuthenticationManager;}OAuth2AuthenticationProcessingFilter?
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException,ServletException {final boolean debug = logger.isDebugEnabled();final HttpServletRequest request = (HttpServletRequest) req;final HttpServletResponse response = (HttpServletResponse) res;try {//提取AuthenticationAuthentication authentication = tokenExtractor.extract(request);//沒(méi)有驗(yàn)證,if (authentication == null) {if (stateless && isAuthenticated()) {if (debug) {logger.debug("Clearing security context.");}SecurityContextHolder.clearContext();}if (debug) {logger.debug("No token in request, will continue chain.");}}else {//設(shè)置ACCESS_TOKEN_VALUE到request,request.setAttribute(OAuth2AuthenticationDetails.ACCESS_TOKEN_VALUE, authentication.getPrincipal());if (authentication instanceof AbstractAuthenticationToken) {AbstractAuthenticationToken needsDetails = (AbstractAuthenticationToken) authentication;needsDetails.setDetails(authenticationDetailsSource.buildDetails(request));}//驗(yàn)證, authenticationManager 是 OAuth2AuthenticationManagerAuthentication authResult = authenticationManager.authenticate(authentication);if (debug) {logger.debug("Authentication success: " + authResult);}eventPublisher.publishAuthenticationSuccess(authResult);SecurityContextHolder.getContext().setAuthentication(authResult);}}catch (OAuth2Exception failed) {SecurityContextHolder.clearContext(); ........return;}chain.doFilter(request, response);}?TokenExtractor?
從請(qǐng)求中提取Authentication?
public interface TokenExtractor {Authentication extract(HttpServletRequest request);}?BearerTokenExtractor
TokenExtractor 的默認(rèn)實(shí)現(xiàn),Bearer方式,從header中提取。
protected String extractHeaderToken(HttpServletRequest request) {Enumeration<String> headers = request.getHeaders("Authorization");while (headers.hasMoreElements()) { // typically there is only one (most servers enforce that)String value = headers.nextElement(); //Bearerif ((value.toLowerCase().startsWith(OAuth2AccessToken.BEARER_TYPE.toLowerCase()))) {String authHeaderValue = value.substring(OAuth2AccessToken.BEARER_TYPE.length()).trim();// Add this here for the auth details later. Would be better to change the signature of this method.request.setAttribute(OAuth2AuthenticationDetails.ACCESS_TOKEN_TYPE,value.substring(0, OAuth2AccessToken.BEARER_TYPE.length()).trim());int commaIndex = authHeaderValue.indexOf(',');if (commaIndex > 0) {authHeaderValue = authHeaderValue.substring(0, commaIndex);}return authHeaderValue;}}return null;}OAuth2AuthenticationManager?
public Authentication authenticate(Authentication authentication) throws AuthenticationException {if (authentication == null) {throw new InvalidTokenException("Invalid token (token not found)");}//獲取token,默認(rèn)是一個(gè)UUID,String token = (String) authentication.getPrincipal();//根據(jù)token獲取AuthenticationOAuth2Authentication auth = tokenServices.loadAuthentication(token);if (auth == null) {throw new InvalidTokenException("Invalid token: " + token);}//資源列表Collection<String> resourceIds = auth.getOAuth2Request().getResourceIds();if (resourceId != null && resourceIds != null && !resourceIds.isEmpty() && !resourceIds.contains(resourceId)) {throw new OAuth2AccessDeniedException("Invalid token does not contain resource id (" + resourceId + ")");}//檢測(cè)客戶(hù)端信息checkClientDetails(auth);if (authentication.getDetails() instanceof OAuth2AuthenticationDetails) {OAuth2AuthenticationDetails details = (OAuth2AuthenticationDetails) authentication.getDetails();// Guard against a cached copy of the same detailsif (!details.equals(auth.getDetails())) {// Preserve the authentication details from the one loaded by token servicesdetails.setDecodedDetails(auth.getDetails());}}auth.setDetails(authentication.getDetails());auth.setAuthenticated(true);return auth;}ResourceServerTokenServices
ResourceServerTokenServices實(shí)現(xiàn)加載Authentication和讀取token的功能。
public interface ResourceServerTokenServices {OAuth2Authentication loadAuthentication(String accessToken) throws AuthenticationException, InvalidTokenException;OAuth2AccessToken readAccessToken(String accessToken); }?流程:
圖從其他地方copy的。
總結(jié)
以上是生活随笔為你收集整理的Spring Security OAuth2源码解析(二)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Spring Security OAut
- 下一篇: Spring Security OAut