鉴权服务器对客户端鉴权之后,会生成token,客户端使用token,就可以去资源服务器获取资源。

@EnableResourceServer 

@Import(ResourceServerConfiguration.class)
public @interface EnableResourceServer {}

ResourceServerConfiguration

ResourceServerConfigurationWebSecurityConfigurerAdapter的子类实现。引入了ResourceServerSecurityConfigurerResourceServerTokenServices

@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);}//匿名验证,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()) {//所有请求需授权http.authorizeRequests().anyRequest().authenticated();}}

ResourceServerSecurityConfigurer

ResourceServerSecurityConfigurer配置了:OAuth2AuthenticationProcessingFilter

@Overridepublic void configure(HttpSecurity http) throws Exception {//如果是OAuth2AuthenticationManager,则设置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);//没有验证,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 {//设置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));}//验证, 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

从请求中提取Authentication

public interface TokenExtractor {Authentication extract(HttpServletRequest request);}

BearerTokenExtractor

TokenExtractor 的默认实现,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,默认是一个UUID,String token = (String) authentication.getPrincipal();//根据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 + ")");}//检测客户端信息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实现加载Authentication和读取token的功能。

public interface ResourceServerTokenServices {OAuth2Authentication loadAuthentication(String accessToken) throws AuthenticationException, InvalidTokenException;OAuth2AccessToken readAccessToken(String accessToken);
}

流程:

图从其他地方copy的。

Spring Security OAuth2源码解析(二)相关推荐

  1. Spring Security OAuth2源码解析(三)——单点登录。

    引入 @EnableOAuth2Client @EnableConfigurationProperties(OAuth2SsoProperties.class) @Import({ OAuth2Sso ...

  2. Spring Security OAuth2源码解析(一)

    目录 引入 AuthorizationServerEndpointsConfiguration 属性 AuthorizationEndpoint OAuth2RequestFactory Defaul ...

  3. Spring Security Oauth2 授权码模式下 自定义登录、授权页面

    主要说明:基于若依springcloud微服务框架的2.1版本 嫌弃缩进不舒服的,直接访问我的博客站点: http://binarydance.top//aticle_view.html?aticle ...

  4. spring aop 注入源码解析

    spring aop 注入源码解析 aop启动 AbstractApplicationContext.java @Overridepublic void refresh() throws BeansE ...

  5. spring aop 注入源码解析 1

    spring aop 注入源码解析 aop启动 AbstractApplicationContext.java @Overridepublic void refresh() throws BeansE ...

  6. Spring 之 @Cacheable 源码解析(上)

    一.@EnableCaching 源码解析 当要使用 @Cacheable 注解时需要引入 @EnableCaching 注解开启缓存功能.为什么呢?现在就来看看为什么要加入 @EnableCachi ...

  7. Spring 之 @Cacheable 源码解析(下)

    CacheInterceptor 缓存切面处理逻辑 接着上篇 Spring 之 @Cacheable 源码解析(上) 说起,代理对象已经创建成功,接着分析调用流程.那么应该从哪里入手呢?当然是去看 A ...

  8. 【深度学习模型】智云视图中文车牌识别源码解析(二)

    [深度学习模型]智云视图中文车牌识别源码解析(二) 感受 HyperLPR可以识别多种中文车牌包括白牌,新能源车牌,使馆车牌,教练车牌,武警车牌等. 代码不可谓不混乱(别忘了这是职业公司的准产品级代码 ...

  9. Spring Security OAuth2 授权码模式 (Authorization Code)

    前言 Spring Security OAuth2 授权码模式 (Authorization Code) 应该是授权登录的一个行业标准 整体流程 首先在平台注册获取CLIENT_ID和CLIENT_S ...

最新文章

  1. jquery java json转字符串_用jQuery以及JSON包将表单数据转为JSON字符串
  2. zlib 1.2.5 编译 ( VS2010 vc6 )
  3. webp app推荐图片格式,更小更快减少oom
  4. 用数组实现从文件搜索帐户和验证密码
  5. 客户端与服务端的TCP通信实现(Qt)
  6. Docker,一个傲娇的男人
  7. 为linux服务器安装rkhunter工具
  8. 016.OpenStack及云计算(面试)常见问题
  9. 微服务化架构演进与人员组织
  10. Docker技术入门与实战 第二版-学习笔记-9-Docker Compose 项目-1-举例说明
  11. 电脑怎么打出冒号符号_标点符号的用法,资深老师带你学习,提高学生学习效率...
  12. 怎么改掉科学计数法_宝宝口唇干裂怎么回事?该怎么办?
  13. 一种低侵入性的组件化方案 之 组件化需要考虑的几个问题
  14. 计算机iq测试,超大多数人类 瑞典天才电脑智商测试得分150
  15. 2020年深圳杯数学建模竞赛A题
  16. 如何裁剪PDF文件的页面大小
  17. python使用阿里云企业邮箱发送邮件
  18. 正则替换非中英文数字 js C#
  19. 电脑4g内存C语言CAD够用吗,电脑4g内存够用吗-电脑4g内存是否够用详情介绍 - 系统家园...
  20. JS实现环绕地球飞行的3D飞行线动画效果(JS+HTML)

热门文章

  1. Web Api 如何做上传文件的单元测试
  2. 关于 UTXO 的思考
  3. Java 面试题 —— 老田的蚂蚁金服面试经历
  4. Linux SSH和SFTP服务分离
  5. java 导出word换行_Java 导出数据库表信息生成Word文档
  6. arcengine根据属性高亮显示图像_新品发布艺卓推出300万像素彩色医疗显示器RX360...
  7. linux生成表格文件大小,如何为linux中的文件夹生成清单(文件列表及其大小和数量)...
  8. groovy附件存mysql_Groovy 操作mysql数据库
  9. MySQL分组函数的使用特点
  10. Nacos源码主动健康检测