org.springframework.security.oauth2.config.annotation.web.configuration下的类详解

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u011676300/article/details/84351569

相关类github链接

注解

EnableAuthorizationServer

EnableAuthorizationServer
表明该类用于配置授权服务

EnableOAuth2Client

EnableOAuth2Client
表明该类用于配置资源服务

EnableResourceServer

EnableResourceServer
表明该类用于配置鉴权服务,核心鉴权逻辑

配置类

AuthorizationServerConfigurer

AuthorizationServerConfigurer
配置OAUth2授权服务器的便捷策略。

  • 用来配置令牌端点(Token Endpoint)的安全约束
/**
	 * Configure the security of the Authorization Server, which means in practical terms the /oauth/token endpoint. The
	 * /oauth/authorize endpoint also needs to be secure, but that is a normal user-facing endpoint and should be
	 * secured the same way as the rest of your UI, so is not covered here. The default settings cover the most common
	 * requirements, following recommendations from the OAuth2 spec, so you don't need to do anything here to get a
	 * basic server up and running.
	 * 
	 * @param security a fluent configurer for security features
	 */
	void configure(AuthorizationServerSecurityConfigurer security) throws Exception;
  • 用来配置客户端详情服务(ClientDetailsService),客户端详情信息在这里进行初始化,你能够把客户端详情信息写死在这里或者是通过数据库来存储调取详情信息

	/**
	 * Configure the {@link ClientDetailsService}, e.g. declaring individual clients and their properties. Note that
	 * password grant is not enabled (even if some clients are allowed it) unless an {@link AuthenticationManager} is
	 * supplied to the {@link #configure(AuthorizationServerEndpointsConfigurer)}. At least one client, or a fully
	 * formed custom {@link ClientDetailsService} must be declared or the server will not start.
	 * 
	 * @param clients the client details configurer
	 */
	void configure(ClientDetailsServiceConfigurer clients) throws Exception;
  • 用来配置授权(authorization)以及令牌(token)的访问端点和令牌服务(token services)
	/**
	 * Configure the non-security features of the Authorization Server endpoints, like token store, token
	 * customizations, user approvals and grant types. You shouldn't need to do anything by default, unless you need
	 * password grants, in which case you need to provide an {@link AuthenticationManager}.
	 * 
	 * @param endpoints the endpoints configurer
	 */
	void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception;

AuthorizationServerConfigurerAdapter

AuthorizationServerConfigurerAdapter
该类实现 AuthorizationServerConfigurer

AuthorizationServerEndpointsConfiguration

AuthorizationServerEndpointsConfiguration

@Configuration
@Import(TokenKeyEndpointRegistrar.class)
public class AuthorizationServerEndpointsConfiguration {

	private AuthorizationServerEndpointsConfigurer endpoints = new AuthorizationServerEndpointsConfigurer();

	@Autowired
	private ClientDetailsService clientDetailsService;

	@Autowired
	private List<AuthorizationServerConfigurer> configurers = Collections.emptyList();

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

	@Bean
	public AuthorizationEndpoint authorizationEndpoint() throws Exception {
		AuthorizationEndpoint authorizationEndpoint = new AuthorizationEndpoint();
		FrameworkEndpointHandlerMapping mapping = getEndpointsConfigurer().getFrameworkEndpointHandlerMapping();
		authorizationEndpoint.setUserApprovalPage(extractPath(mapping, "/oauth/confirm_access"));
		authorizationEndpoint.setProviderExceptionHandler(exceptionTranslator());
		authorizationEndpoint.setErrorPage(extractPath(mapping, "/oauth/error"));
		authorizationEndpoint.setTokenGranter(tokenGranter());
		authorizationEndpoint.setClientDetailsService(clientDetailsService);
		authorizationEndpoint.setAuthorizationCodeServices(authorizationCodeServices());
		authorizationEndpoint.setOAuth2RequestFactory(oauth2RequestFactory());
		authorizationEndpoint.setOAuth2RequestValidator(oauth2RequestValidator());
		authorizationEndpoint.setUserApprovalHandler(userApprovalHandler());
		authorizationEndpoint.setRedirectResolver(redirectResolver());
		return authorizationEndpoint;
	}

	@Bean
	public TokenEndpoint tokenEndpoint() throws Exception {
		TokenEndpoint tokenEndpoint = new TokenEndpoint();
		tokenEndpoint.setClientDetailsService(clientDetailsService);
		tokenEndpoint.setProviderExceptionHandler(exceptionTranslator());
		tokenEndpoint.setTokenGranter(tokenGranter());
		tokenEndpoint.setOAuth2RequestFactory(oauth2RequestFactory());
		tokenEndpoint.setOAuth2RequestValidator(oauth2RequestValidator());
		tokenEndpoint.setAllowedRequestMethods(allowedTokenEndpointRequestMethods());
		return tokenEndpoint;
	}

	@Bean
	public CheckTokenEndpoint checkTokenEndpoint() {
		CheckTokenEndpoint endpoint = new CheckTokenEndpoint(getEndpointsConfigurer().getResourceServerTokenServices());
		endpoint.setAccessTokenConverter(getEndpointsConfigurer().getAccessTokenConverter());
		endpoint.setExceptionTranslator(exceptionTranslator());
		return endpoint;
	}

	@Bean
	public WhitelabelApprovalEndpoint whitelabelApprovalEndpoint() {
		return new WhitelabelApprovalEndpoint();
	}

	@Bean
	public WhitelabelErrorEndpoint whitelabelErrorEndpoint() {
		return new WhitelabelErrorEndpoint();
	}

	@Bean
	public FrameworkEndpointHandlerMapping oauth2EndpointHandlerMapping() throws Exception {
		return getEndpointsConfigurer().getFrameworkEndpointHandlerMapping();
	}

	@Bean
	public FactoryBean<ConsumerTokenServices> consumerTokenServices() throws Exception {
		return new AbstractFactoryBean<ConsumerTokenServices>() {

			@Override
			public Class<?> getObjectType() {
				return ConsumerTokenServices.class;
			}

			@Override
			protected ConsumerTokenServices createInstance() throws Exception {
				return getEndpointsConfigurer().getConsumerTokenServices();
			}
		};
	}

	/**
	 * This needs to be a <code>@Bean</code> so that it can be
	 * <code>@Transactional</code> (in case the token store supports them). If
	 * you are overriding the token services in an
	 * {@link AuthorizationServerConfigurer} consider making it a
	 * <code>@Bean</code> for the same reason (assuming you need transactions,
	 * e.g. for a JDBC token store).
	 * 
	 * @return an AuthorizationServerTokenServices
	 */
	@Bean
	public FactoryBean<AuthorizationServerTokenServices> defaultAuthorizationServerTokenServices() {
		return new AuthorizationServerTokenServicesFactoryBean(endpoints);
	}

	public AuthorizationServerEndpointsConfigurer getEndpointsConfigurer() {
		if (!endpoints.isTokenServicesOverride()) {
			try {
				endpoints.tokenServices(endpoints.getDefaultAuthorizationServerTokenServices());
			}
			catch (Exception e) {
				throw new BeanCreationException("Cannot create token services", e);
			}
		}
		return endpoints;
	}

	private Set<HttpMethod> allowedTokenEndpointRequestMethods() {
		return getEndpointsConfigurer().getAllowedTokenEndpointRequestMethods();
	}

	private OAuth2RequestFactory oauth2RequestFactory() throws Exception {
		return getEndpointsConfigurer().getOAuth2RequestFactory();
	}

	private UserApprovalHandler userApprovalHandler() throws Exception {
		return getEndpointsConfigurer().getUserApprovalHandler();
	}

	private OAuth2RequestValidator oauth2RequestValidator() throws Exception {
		return getEndpointsConfigurer().getOAuth2RequestValidator();
	}

	private AuthorizationCodeServices authorizationCodeServices() throws Exception {
		return getEndpointsConfigurer().getAuthorizationCodeServices();
	}

	private WebResponseExceptionTranslator<OAuth2Exception> exceptionTranslator() {
		return getEndpointsConfigurer().getExceptionTranslator();
	}

	private RedirectResolver redirectResolver() {
		return getEndpointsConfigurer().getRedirectResolver();
	}

	private TokenGranter tokenGranter() throws Exception {
		return getEndpointsConfigurer().getTokenGranter();
	}

	private String extractPath(FrameworkEndpointHandlerMapping mapping, String page) {
		String path = mapping.getPath(page);
		if (path.contains(":")) {
			return path;
		}
		return "forward:" + path;
	}

	protected static class AuthorizationServerTokenServicesFactoryBean
			extends AbstractFactoryBean<AuthorizationServerTokenServices> {

		private AuthorizationServerEndpointsConfigurer endpoints;
		
		protected AuthorizationServerTokenServicesFactoryBean() {
		}

		public AuthorizationServerTokenServicesFactoryBean(
				AuthorizationServerEndpointsConfigurer endpoints) {
					this.endpoints = endpoints;
		}

		@Override
		public Class<?> getObjectType() {
			return AuthorizationServerTokenServices.class;
		}

		@Override
		protected AuthorizationServerTokenServices createInstance() throws Exception {
			return endpoints.getDefaultAuthorizationServerTokenServices();
		}
	}

	@Component
	protected static class TokenKeyEndpointRegistrar implements BeanDefinitionRegistryPostProcessor {

		private BeanDefinitionRegistry registry;

		@Override
		public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
			String[] names = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(beanFactory,
					JwtAccessTokenConverter.class, false, false);
			if (names.length > 0) {
				BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(TokenKeyEndpoint.class);
				builder.addConstructorArgReference(names[0]);
				registry.registerBeanDefinition(TokenKeyEndpoint.class.getName(), builder.getBeanDefinition());
			}
		}

		@Override
		public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
			this.registry = registry;
		}

	}

}

AuthorizationServerSecurityConfiguration

AuthorizationServerSecurityConfiguration
继承

AuthorizationServerSecurityConfiguration extends WebSecurityConfigurerAdapter

实现源码

@Autowired
	private List<AuthorizationServerConfigurer> configurers = Collections.emptyList();

	@Autowired
	private ClientDetailsService clientDetailsService;

	@Autowired
	private AuthorizationServerEndpointsConfiguration endpoints;

	@Autowired
	public void configure(ClientDetailsServiceConfigurer clientDetails) throws Exception {
		for (AuthorizationServerConfigurer configurer : configurers) {
			configurer.configure(clientDetails);
		}
	}

	@Override
	protected void configure(AuthenticationManagerBuilder auth) throws Exception {
		// Over-riding to make sure this.disableLocalConfigureAuthenticationBldr = false
		// This will ensure that when this configurer builds the AuthenticationManager it will not attempt
		// to find another 'Global' AuthenticationManager in the ApplicationContext (if available),
		// and set that as the parent of this 'Local' AuthenticationManager.
		// This AuthenticationManager should only be wired up with an AuthenticationProvider
		// composed of the ClientDetailsService (wired in this configuration) for authenticating 'clients' only.
	}

	@Override
	protected void configure(HttpSecurity http) throws Exception {
		AuthorizationServerSecurityConfigurer configurer = new AuthorizationServerSecurityConfigurer();
		FrameworkEndpointHandlerMapping handlerMapping = endpoints.oauth2EndpointHandlerMapping();
		http.setSharedObject(FrameworkEndpointHandlerMapping.class, handlerMapping);
		configure(configurer);
		http.apply(configurer);
		String tokenEndpointPath = handlerMapping.getServletPath("/oauth/token");
		String tokenKeyPath = handlerMapping.getServletPath("/oauth/token_key");
		String checkTokenPath = handlerMapping.getServletPath("/oauth/check_token");
		if (!endpoints.getEndpointsConfigurer().isUserDetailsServiceOverride()) {
			UserDetailsService userDetailsService = http.getSharedObject(UserDetailsService.class);
			endpoints.getEndpointsConfigurer().userDetailsService(userDetailsService);
		}
		// @formatter:off
		http
        	.authorizeRequests()
            	.antMatchers(tokenEndpointPath).fullyAuthenticated()
            	.antMatchers(tokenKeyPath).access(configurer.getTokenKeyAccess())
            	.antMatchers(checkTokenPath).access(configurer.getCheckTokenAccess())
        .and()
        	.requestMatchers()
            	.antMatchers(tokenEndpointPath, tokenKeyPath, checkTokenPath)
        .and()
        	.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.NEVER);
		// @formatter:on
		http.setSharedObject(ClientDetailsService.class, clientDetailsService);
	}

	protected void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
		for (AuthorizationServerConfigurer configurer : configurers) {
			configurer.configure(oauthServer);
		}
	}

OAuth2ClientConfiguration

OAuth2ClientConfiguration
实现源码


	@Bean
	public OAuth2ClientContextFilter oauth2ClientContextFilter() {
		OAuth2ClientContextFilter filter = new OAuth2ClientContextFilter();
		return filter;
	}

	@Bean
	@Scope(value = "request", proxyMode = ScopedProxyMode.INTERFACES)
	protected AccessTokenRequest accessTokenRequest(@Value("#{request.parameterMap}")
	Map<String, String[]> parameters, @Value("#{request.getAttribute('currentUri')}")
	String currentUri) {
		DefaultAccessTokenRequest request = new DefaultAccessTokenRequest(parameters);
		request.setCurrentUri(currentUri);
		return request;
	}
	
	@Configuration
	protected static class OAuth2ClientContextConfiguration {
		
		@Resource
		@Qualifier("accessTokenRequest")
		private AccessTokenRequest accessTokenRequest;
		
		@Bean
		@Scope(value = "session", proxyMode = ScopedProxyMode.INTERFACES)
		public OAuth2ClientContext oauth2ClientContext() {
			return new DefaultOAuth2ClientContext(accessTokenRequest);
		}
		
	}

ResourceServerConfiguration

ResourceServerConfiguration

public class ResourceServerConfiguration extends WebSecurityConfigurerAdapter implements Ordered {

	private int order = 3;

	@Autowired(required = false)
	private TokenStore tokenStore;

	@Autowired(required = false)
	private AuthenticationEventPublisher eventPublisher;

	@Autowired(required = false)
	private Map<String, ResourceServerTokenServices> tokenServices;

	@Autowired
	private ApplicationContext context;

	private List<ResourceServerConfigurer> configurers = Collections.emptyList();

	@Autowired(required = false)
	private AuthorizationServerEndpointsConfiguration endpoints;

	@Override
	public int getOrder() {
		return order;
	}

	public void setOrder(int order) {
		this.order = order;
	}

	/**
	 * @param configurers the configurers to set
	 */
	@Autowired(required = false)
	public void setConfigurers(List<ResourceServerConfigurer> configurers) {
		this.configurers = configurers;
	}

	private static class NotOAuthRequestMatcher implements RequestMatcher {

		private FrameworkEndpointHandlerMapping mapping;

		public NotOAuthRequestMatcher(FrameworkEndpointHandlerMapping mapping) {
			this.mapping = mapping;
		}

		@Override
		public boolean matches(HttpServletRequest request) {
			String requestPath = getRequestPath(request);
			for (String path : mapping.getPaths()) {
				if (requestPath.startsWith(mapping.getPath(path))) {
					return false;
				}
			}
			return true;
		}

		private String getRequestPath(HttpServletRequest request) {
			String url = request.getServletPath();

			if (request.getPathInfo() != null) {
				url += request.getPathInfo();
			}

			return url;
		}

	}

	@Override
	protected void configure(HttpSecurity http) throws Exception {
		ResourceServerSecurityConfigurer resources = new ResourceServerSecurityConfigurer();
		ResourceServerTokenServices 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);
		}
		// @formatter:off
		http.authenticationProvider(new AnonymousAuthenticationProvider("default"))
		// N.B. exceptionHandling is duplicated in resources.configure() so that
		// it works
		.exceptionHandling()
				.accessDeniedHandler(resources.getAccessDeniedHandler()).and()
				.sessionManagement()
				.sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
				.csrf().disable();
		// @formatter:on
		http.apply(resources);
		if (endpoints != null) {
			// Assume we are in an Authorization Server
			http.requestMatcher(new NotOAuthRequestMatcher(endpoints.oauth2EndpointHandlerMapping()));
		}
		for (ResourceServerConfigurer configurer : configurers) {
			// Delegates can add authorizeRequests() here
			configurer.configure(http);
		}
		if (configurers.isEmpty()) {
			// Add anyRequest() last as a fall back. Spring Security would
			// replace an existing anyRequest() matcher with this one, so to
			// avoid that we only add it if the user hasn't configured anything.
			http.authorizeRequests().anyRequest().authenticated();
		}
	}

	private ResourceServerTokenServices resolveTokenServices() {
		if (tokenServices == null || tokenServices.size() == 0) {
			return null;
		}
		if (tokenServices.size() == 1) {
			return tokenServices.values().iterator().next();
		}
		if (tokenServices.size() == 2) {
			// Maybe they are the ones provided natively
			Iterator<ResourceServerTokenServices> iter = tokenServices.values().iterator();
			ResourceServerTokenServices one = iter.next();
			ResourceServerTokenServices two = iter.next();
			if (elementsEqual(one, two)) {
				return one;
			}
		}
		return context.getBean(ResourceServerTokenServices.class);
	}

	private boolean elementsEqual(Object one, Object two) {
		// They might just be equal
		if (one == two) {
			return true;
		}
		Object targetOne = findTarget(one);
		Object targetTwo = findTarget(two);
		return targetOne == targetTwo;
	}

	private Object findTarget(Object item) {
		Object current = item;
		while (current instanceof Advised) {
			try {
				current = ((Advised) current).getTargetSource().getTarget();
			}
			catch (Exception e) {
				ReflectionUtils.rethrowRuntimeException(e);
			}
		}
		return current;
	}

}

ResourceServerConfigurer

ResourceServerConfigurer

/**
	 * Add resource-server specific properties (like a resource id). The defaults should work for many applications, but
	 * you might want to change at least the resource id.
	 * 
	 * @param resources configurer for the resource server
	 * @throws Exception if there is a problem
	 */
	void configure(ResourceServerSecurityConfigurer resources) throws Exception;

	/**
	 * Use this to configure the access rules for secure resources. By default all resources <i>not</i> in "/oauth/**"
	 * are protected (but no specific rules about scopes are given, for instance). You also get an
	 * {@link OAuth2WebSecurityExpressionHandler} by default.
	 * 
	 * @param http the current http filter configuration
	 * @throws Exception if there is a problem
	 */
	void configure(HttpSecurity http) throws Exception;

ResourceServerConfigurerAdapter

ResourceServerConfigurerAdapter

实现ResourceServerConfigurer接口

展开阅读全文

没有更多推荐了,返回首页