前言

在学习新框架的时候,先是了解怎么用,在是去了解运行流程、加载流程、然后再试二次开发,本文是针对SpringSecurityOAuth2授权加载流程进行分析

源码分析

1.加载AuthorizationServerConfig
SpringSecurityOAuth2授权流程加载源码分析_其他

这个类就是标注@EnableAuthorizationServer的配置类,也就是授权服配置类,AuthorizationServerConfig实例化时会进入父类AuthorizationServerConfigurerAdapter进行加载,然后会完AuthorizationServerConfig类中一些列自动注入,如authenticationManager、dataSource、passwordEncoder、tokenGranter等注入,我这个AuthorizationServerConfig配置类中只用到了这些,在自动注入这些属性的时候,等AuthorizationServerConfig完成初始化后,这里有一个关键点,就是@EnableAuthorizationServer这个注解,点进去
SpringSecurityOAuth2授权流程加载源码分析_其他_02
这个接口中有@Import导入的AuthorizationServerEndpointsConfiguration,AuthorizationServerConfig加载完后就会加载AuthorizationServerEndpointsConfiguration,AuthorizationServerEndpointsConfiguration源码如下!
SpringSecurityOAuth2授权流程加载源码分析_初始化_03
这里有两个比较重要的地方。

private AuthorizationServerEndpointsConfigurer endpoints = new AuthorizationServerEndpointsConfigurer();

这个是授权服配置类中public void configure(AuthorizationServerEndpointsConfigurer endpoints)这个方法配置的对象都会存储在上面的代码创建的对象中
SpringSecurityOAuth2授权流程加载源码分析_其他_04
还一个就是

	@PostConstruct
	public void init() {
		for (AuthorizationServerConfigurer configurer : configurers) {
			try {
				configurer.configure(endpoints);
			} catch (Exception e) {
				throw new IllegalStateException("Cannot configure enpdoints", e);
			}
		}
		endpoints.setClientDetailsService(clientDetailsService);
	}

这个代码就是在是在依赖注入之后调用的,补充一下这个知识点

@PostConstruct注解好多人以为是Spring提供的。其实是Java自己的注解。
Java中该注解的说明:@PostConstruct该注解被用来修饰一个非静态的void()方法。被@PostConstruct修饰的方法会在服务器加载Servlet的时候运行,并且只会被服务器执行一次。PostConstruct在构造函数之后执行,init()方法之前执行。
通常我们会是在Spring框架中使用到@PostConstruct注解 该注解的方法在整个Bean初始化中的执行顺序:
Constructor(构造方法) -> @Autowired(依赖注入) -> @PostConstruct(注释的方法)

当这个方法执行前AuthorizationServerEndpointsConfiguration对象中已经有了endpoints、clientDetailsService、configurers。
endpoints上面已经介绍了。clientDetailsService这个不过多解释你们也知道,configurers这个是所有实现AuthorizationServerConfigurer接口的类(Spring使用@Autowired将实现类注入List或者Map中),这里其实也就是我们上面的AuthorizationServerConfig类,按照init()方法的逻辑就是遍历所有实现AuthorizationServerConfigurer接口的类挨个调用public void configure(AuthorizationServerEndpointsConfigurer endpoints)方法,也就是下面代码
SpringSecurityOAuth2授权流程加载源码分析_spring_05
会将这些配置的值,通过引用传递给AuthorizationServerEndpointsConfiguration类中的endpoints属性。这里也就是比较核心的一个点,然后这个方法执行完成后那么系统中的一些配置就挂载到AuthorizationServerEndpointsConfiguration类的endpoints属性中,其中包括TokenGranter(token授权模式)、TokenStore(token存储策略)、TokenEnhancer(token生成策略)、等一些配置挂载到endpoints中存储。然后这里执行完成后还会加载一些Bean,如下
SpringSecurityOAuth2授权流程加载源码分析_初始化_06
这些Bean其实就是一些Controller,不信你看!
SpringSecurityOAuth2授权流程加载源码分析_spring_07
其实也就是将这些Bean注入到Spring容器是设置一些初始值,这里需要注意,又是一个核心点!我这里拿tokenEndpoint()方法举例

	@Bean
	public TokenEndpoint tokenEndpoint() throws Exception {
		TokenEndpoint tokenEndpoint = new TokenEndpoint();
		tokenEndpoint.setClientDetailsService(clientDetailsService);
		tokenEndpoint.setProviderExceptionHandler(exceptionTranslator());
		//这行代码很关键tokenEndpoint.setTokenGranter(tokenGranter()),这里调用的是TokenEndpoint 父类中的setTokenGranter方法!完成TokenGranter的复赋值操作!
		tokenEndpoint.setTokenGranter(tokenGranter());
		tokenEndpoint.setOAuth2RequestFactory(oauth2RequestFactory());
		tokenEndpoint.setOAuth2RequestValidator(oauth2RequestValidator());
		tokenEndpoint.setAllowedRequestMethods(allowedTokenEndpointRequestMethods());
		return tokenEndpoint;
	}

这个Bean加载后,那么整个系统中TokenEndpoint 就完成初始化了,我们请求的/oauth/token这个接口中,如下
SpringSecurityOAuth2授权流程加载源码分析_加载_08
那么到代码运行到这一行时就能获取到TokenGranter,

OAuth2AccessToken token = getTokenGranter().grant(tokenRequest.getGrantType(), tokenRequest);

获取到TokenGranter它了,那么就可以到获取令牌的流程上,接下来的流程请见SpringSecurityOAuth2授权流程源码分析