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

引入

@EnableOAuth2Client
@EnableConfigurationProperties(OAuth2SsoProperties.class)
@Import({ OAuth2SsoDefaultConfiguration.class, OAuth2SsoCustomConfiguration.class,
		ResourceServerTokenServicesConfiguration.class })
public @interface EnableOAuth2Sso {

}

EnableOAuth2Sso注解引入了3个配置类:OAuth2SsoDefaultConfigurationOAuth2SsoCustomConfigurationResourceServerTokenServicesConfiguration和一个属性类OAuth2SsoProperties

OAuth2SsoProperties 

OAuth2SsoProperties 主要用于设置单点登录login path。

@ConfigurationProperties(prefix = "security.oauth2.sso")
public class OAuth2SsoProperties {

	public static final String DEFAULT_LOGIN_PATH = "/login";
}

ResourceServerTokenServicesConfiguration

ResourceServerTokenServicesConfiguration用于引入资源服务,token服务的配置信息。

OAuth2SsoDefaultConfiguration

OAuth2SsoDefaultConfiguration实现WebSecurityConfigurerAdapter。所有资源都需要验证。

同时引入了配置SsoSecurityConfigurer

	@Override
	protected void configure(HttpSecurity http) throws Exception {
		http.antMatcher("/**").authorizeRequests().anyRequest().authenticated();
		new SsoSecurityConfigurer(this.applicationContext).configure(http);
	}

 SsoSecurityConfigurer

SsoSecurityConfigurer引入了OAuth2ClientAuthenticationProcessingFilter

		@Override
		public void configure(HttpSecurity builder) throws Exception {
			OAuth2ClientAuthenticationProcessingFilter ssoFilter = this.filter;
			ssoFilter.setSessionAuthenticationStrategy(builder.getSharedObject(SessionAuthenticationStrategy.class));
			builder.addFilterAfter(ssoFilter, AbstractPreAuthenticatedProcessingFilter.class);
		}

OAuth2ClientAuthenticationProcessingFilter

OAuth2ClientAuthenticationProcessingFilter过滤器 其要完成的工作就是 通过获取到的code码调用 授权服务 /oauth/token 接口获取 token 信息,并将获取到的token 信息解析成 OAuth2Authentication 认证对象。

	@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;			
		}

	}

OAuth2SsoCustomConfiguration

OAuth2SsoCustomConfiguration用于给ProxyFactory增加AOP

public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		if (this.configType.isAssignableFrom(bean.getClass()) && bean instanceof WebSecurityConfigurerAdapter) {
			ProxyFactory factory = new ProxyFactory();
			factory.setTarget(bean);
			factory.addAdvice(new SsoSecurityAdapter(this.applicationContext));
			bean = factory.getProxy();
		}
		return bean;
	}
private static class SsoSecurityAdapter implements MethodInterceptor {

		private SsoSecurityConfigurer configurer;

		SsoSecurityAdapter(ApplicationContext applicationContext) {
			this.configurer = new SsoSecurityConfigurer(applicationContext);
		}

		@Override
		public Object invoke(MethodInvocation invocation) throws Throwable {
			if (invocation.getMethod().getName().equals("init")) {
				Method method = ReflectionUtils.findMethod(WebSecurityConfigurerAdapter.class, "getHttp");
				ReflectionUtils.makeAccessible(method);
				HttpSecurity http = (HttpSecurity) ReflectionUtils.invokeMethod(method, invocation.getThis());
				this.configurer.configure(http);
			}
			return invocation.proceed();
		}

	}

猜你喜欢

转载自blog.csdn.net/demon7552003/article/details/107879164