Spring Security OAuth2源码解析(二)
鉴权服务器对客户端鉴权之后,会生成token,客户端使用token,就可以去资源服务器获取资源。
@EnableResourceServer
@Import(ResourceServerConfiguration.class)
public @interface EnableResourceServer {}
ResourceServerConfiguration
ResourceServerConfiguration是WebSecurityConfigurerAdapter的子类实现。引入了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);}//匿名验证,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源码解析(二)相关推荐
- Spring Security OAuth2源码解析(三)——单点登录。
引入 @EnableOAuth2Client @EnableConfigurationProperties(OAuth2SsoProperties.class) @Import({ OAuth2Sso ...
- Spring Security OAuth2源码解析(一)
目录 引入 AuthorizationServerEndpointsConfiguration 属性 AuthorizationEndpoint OAuth2RequestFactory Defaul ...
- Spring Security Oauth2 授权码模式下 自定义登录、授权页面
主要说明:基于若依springcloud微服务框架的2.1版本 嫌弃缩进不舒服的,直接访问我的博客站点: http://binarydance.top//aticle_view.html?aticle ...
- spring aop 注入源码解析
spring aop 注入源码解析 aop启动 AbstractApplicationContext.java @Overridepublic void refresh() throws BeansE ...
- spring aop 注入源码解析 1
spring aop 注入源码解析 aop启动 AbstractApplicationContext.java @Overridepublic void refresh() throws BeansE ...
- Spring 之 @Cacheable 源码解析(上)
一.@EnableCaching 源码解析 当要使用 @Cacheable 注解时需要引入 @EnableCaching 注解开启缓存功能.为什么呢?现在就来看看为什么要加入 @EnableCachi ...
- Spring 之 @Cacheable 源码解析(下)
CacheInterceptor 缓存切面处理逻辑 接着上篇 Spring 之 @Cacheable 源码解析(上) 说起,代理对象已经创建成功,接着分析调用流程.那么应该从哪里入手呢?当然是去看 A ...
- 【深度学习模型】智云视图中文车牌识别源码解析(二)
[深度学习模型]智云视图中文车牌识别源码解析(二) 感受 HyperLPR可以识别多种中文车牌包括白牌,新能源车牌,使馆车牌,教练车牌,武警车牌等. 代码不可谓不混乱(别忘了这是职业公司的准产品级代码 ...
- Spring Security OAuth2 授权码模式 (Authorization Code)
前言 Spring Security OAuth2 授权码模式 (Authorization Code) 应该是授权登录的一个行业标准 整体流程 首先在平台注册获取CLIENT_ID和CLIENT_S ...
最新文章
- jquery java json转字符串_用jQuery以及JSON包将表单数据转为JSON字符串
- zlib 1.2.5 编译 ( VS2010 vc6 )
- webp app推荐图片格式,更小更快减少oom
- 用数组实现从文件搜索帐户和验证密码
- 客户端与服务端的TCP通信实现(Qt)
- Docker,一个傲娇的男人
- 为linux服务器安装rkhunter工具
- 016.OpenStack及云计算(面试)常见问题
- 微服务化架构演进与人员组织
- Docker技术入门与实战 第二版-学习笔记-9-Docker Compose 项目-1-举例说明
- 电脑怎么打出冒号符号_标点符号的用法,资深老师带你学习,提高学生学习效率...
- 怎么改掉科学计数法_宝宝口唇干裂怎么回事?该怎么办?
- 一种低侵入性的组件化方案 之 组件化需要考虑的几个问题
- 计算机iq测试,超大多数人类 瑞典天才电脑智商测试得分150
- 2020年深圳杯数学建模竞赛A题
- 如何裁剪PDF文件的页面大小
- python使用阿里云企业邮箱发送邮件
- 正则替换非中英文数字 js C#
- 电脑4g内存C语言CAD够用吗,电脑4g内存够用吗-电脑4g内存是否够用详情介绍 - 系统家园...
- JS实现环绕地球飞行的3D飞行线动画效果(JS+HTML)
热门文章
- Web Api 如何做上传文件的单元测试
- 关于 UTXO 的思考
- Java 面试题 —— 老田的蚂蚁金服面试经历
- Linux SSH和SFTP服务分离
- java 导出word换行_Java 导出数据库表信息生成Word文档
- arcengine根据属性高亮显示图像_新品发布艺卓推出300万像素彩色医疗显示器RX360...
- linux生成表格文件大小,如何为linux中的文件夹生成清单(文件列表及其大小和数量)...
- groovy附件存mysql_Groovy 操作mysql数据库
- MySQL分组函数的使用特点
- Nacos源码主动健康检测