Spring Security Config : AbstractInterceptUrlConfigurer

概述

介绍

AbstractInterceptUrlConfigurerSpring Security Config的一个安全配置器抽象基类。它定义了为安全构建器HttpSecurity配置一个FilterSecurityInterceptor的安全配置器的通用行为逻辑。具体定义如下 :

  • 安全配置器接口SecurityConfigurer约定的配置方法 configure

    对目标安全构建器 http 进行配置,http 实际上可以理解成就是HttpSecurity
    主要就是调用当前类所定义的各种方法创建目标FilterSecurityInterceptor并设置到目标安全构建器http

  • 抽象方法 createMetadataSource

    抽象方法,要求子类提供实现。用于创建安全元数据对象FilterInvocationSecurityMetadataSource,供目标安全拦截过滤器FilterSecurityInterceptor使用。

  • 抽象方法 getDecisionVoters

    抽象方法,要求子类提供实现。创建缺省AccessDecisionManager的方法createDefaultAccessDecisionManager会用到这个方法提供的一组AccessDecisionVoter

  • 私有方法 createDefaultAccessDecisionManager

    创建目标FilterSecurityInterceptor用到的AccessDecisionManager可以由调用者设置,如果不设置,则使用该方法创建一个缺省的AccessDecisionManager,该缺省的AccessDecisionManager实现类使用AffirmativeBased,一票赞成即可通过。

  • 私有方法 getAccessDecisionManager

    该方法被configure用于获取最终用于目标FilterSecurityInterceptor要使用的AccessDecisionManager。如果调用者设置了当前安全配置器的AccessDecisionManager属性则使用它,否则使用createDefaultAccessDecisionManager创建一个缺省的AccessDecisionManager

  • 私有方法 createFilterSecurityInterceptor

    创建createFilterSecurityInterceptor的具体过程方法。configure正式使用该方法创建FilterSecurityInterceptor,然后设置到目标安全构建器http

  • 内嵌静态类抽象类 AbstractInterceptUrlRegistry

    该类继承自AbstractConfigAttributeRequestMatcherRegistry,表示一个URL pattern到所需的权限的映射表。这里每个映射项内部通过AbstractConfigAttributeRequestMatcherRegistry.UrlMapping来表示,其中URL pattern通过RequestMatcher来表示,所需要的权限通过ConfigAttribute集合来表示。该映射表是构建目标FilterSecurityInterceptor所要使用的安全元数据源SecurityMetadataSource对象的来源。
    AbstractInterceptUrlRegistry也必须要由AbstractInterceptUrlConfigurer的具体实现子类提供自己的具体实现类。

继承关系

AbstractInterceptUrlConfigurer

源代码

源代码版本 Spring Security Config 5.1.4.RELEASE

package org.springframework.security.config.annotation.web.configurers;

import java.util.List;

import org.springframework.security.access.AccessDecisionManager;
import org.springframework.security.access.AccessDecisionVoter;
import org.springframework.security.access.vote.AffirmativeBased;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.SecurityConfigurer;
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;

/**
 * A base class for configuring the FilterSecurityInterceptor.
 *
 *
 * @param <C> the AbstractInterceptUrlConfigurer
 * @param <H> the type of HttpSecurityBuilder that is being configured
 *
 * @author Rob Winch
 * @since 3.2
 * @see ExpressionUrlAuthorizationConfigurer
 * @see UrlAuthorizationConfigurer
 */
abstract class AbstractInterceptUrlConfigurer<C extends AbstractInterceptUrlConfigurer<C, H>, 
		H extends HttpSecurityBuilder<H>>
		extends AbstractHttpConfigurer<C, H> {
	private Boolean filterSecurityInterceptorOncePerRequest;

	private AccessDecisionManager accessDecisionManager;

   // 接口 SecurityConfigurer 定义的配置方法,对目标安全构建器 http 进行配置, http 实际上可以理解成就是
   // HttpSecurity
	@Override
	public void configure(H http) throws Exception {
       // 创建 FilterInvocationSecurityMetadataSource, FilterInvocationSecurityMetadataSource
       // 是接下来创建 FilterSecurityInterceptor 所需要的, 在该类中,createMetadataSource方法
       // 是一个抽象方法,也就是说,其实现逻辑必须有该类的实现子类提供。
		FilterInvocationSecurityMetadataSource metadataSource = createMetadataSource(http);
		if (metadataSource == null) {
			return;
		}
        
       // 创建  FilterSecurityInterceptor, 方法 createFilterSecurityInterceptor 的逻辑由本类提供,
       // 并且被定义为 private,无需由子类覆盖,
       // 这里创建 FilterSecurityInterceptor 使用到了 :
       // 1. 目标安全构建器 http
       // 2. 上面创建的安全元数据对象 metadataSource
       // 3. 保存在目标安全构建器中的 AuthenticationManager 共享对象
		FilterSecurityInterceptor securityInterceptor = createFilterSecurityInterceptor(
				http, metadataSource, http.getSharedObject(AuthenticationManager.class));
		if (filterSecurityInterceptorOncePerRequest != null) {
			securityInterceptor
					.setObserveOncePerRequest(filterSecurityInterceptorOncePerRequest);
		}
       // 对新建安全拦截过滤器 FilterSecurityInterceptor 的后置处理
		securityInterceptor = postProcess(securityInterceptor);
        
       // 将新建的安全拦截过滤器  FilterSecurityInterceptor 添加到目标安全构建器 http 的Filter清单,
       // 也添加为目标安全构建器的一个共享对象
		http.addFilter(securityInterceptor);
		http.setSharedObject(FilterSecurityInterceptor.class, securityInterceptor);
	}

	/**
	 * Subclasses should implement this method to provide a
	 * FilterInvocationSecurityMetadataSource for the
	 * FilterSecurityInterceptor.
	 *
	 * @param http the builder to use
	 *
	 * @return the FilterInvocationSecurityMetadataSource to set on the
	 * FilterSecurityInterceptor. Cannot be null.
	 */
	abstract FilterInvocationSecurityMetadataSource createMetadataSource(H http);

	/**
	 * Subclasses should implement this method to provide the AccessDecisionVoter
	 * instances used to create the default AccessDecisionManager
	 *
	 * @param http the builder to use
	 *
	 * @return the AccessDecisionVoter instances used to create the default
	 * {@link AccessDecisionManager}
	 */
	abstract List<AccessDecisionVoter<? extends Object>> getDecisionVoters(H http);

	abstract class AbstractInterceptUrlRegistry<R extends AbstractInterceptUrlRegistry<R, T>, T>
			extends AbstractConfigAttributeRequestMatcherRegistry<T> {

		/**
		 * Allows setting the AccessDecisionManager. If none is provided, a
		 * default AccessDecisionManager is created.
		 *
		 * @param accessDecisionManager the AccessDecisionManager to use
		 * @return the AbstractInterceptUrlConfigurer for further customization
		 */
		public R accessDecisionManager(AccessDecisionManager accessDecisionManager) {
			AbstractInterceptUrlConfigurer.this.accessDecisionManager = accessDecisionManager;
			return getSelf();
		}

		/**
		 * Allows setting if the FilterSecurityInterceptor should be only applied
		 * once per request (i.e. if the filter intercepts on a forward, should it be
		 * applied again).
		 *
		 * @param filterSecurityInterceptorOncePerRequest if the
		 * FilterSecurityInterceptor should be only applied once per request
		 * @return the AbstractInterceptUrlConfigurer for further customization
		 */
		public R filterSecurityInterceptorOncePerRequest(
				boolean filterSecurityInterceptorOncePerRequest) {
			AbstractInterceptUrlConfigurer.this.filterSecurityInterceptorOncePerRequest =
				 filterSecurityInterceptorOncePerRequest;
			return getSelf();
		}

		/**
		 * Returns a reference to the current object with a single suppression of the type
		 *
		 * @return a reference to the current object
		 */
		@SuppressWarnings("unchecked")
		private R getSelf() {
			return (R) this;
		}
	}

	/**
	 * Creates the default AccessDecisionManager
	 * @return the default AccessDecisionManager
	 */
	private AccessDecisionManager createDefaultAccessDecisionManager(H http) {
       // 创建缺省使用的 AccessDecisionManager, 注意该缺省 AccessDecisionManager
       // 是一个 AffirmativeBased, 也就是只要有一票赞成即通过
		AffirmativeBased result = new AffirmativeBased(getDecisionVoters(http));
		return postProcess(result);
	}

	/**
	 * If currently null, creates a default AccessDecisionManager using
	 * #createDefaultAccessDecisionManager(HttpSecurityBuilder). Otherwise returns the
	 * AccessDecisionManager.
	 *
	 * @param http the builder to use
	 *
	 * @return the AccessDecisionManager to use
	 */
	private AccessDecisionManager getAccessDecisionManager(H http) {
       // 获取配置过程最终要使用的 AccessDecisionManager, 该 AccessDecisionManager
       // 可以由调用者指定,如果不指定,则使用缺省值,一个 AffirmativeBased:一票赞成即通过
		if (accessDecisionManager == null) {
			accessDecisionManager = createDefaultAccessDecisionManager(http);
		}
		return accessDecisionManager;
	}

	/**
	 * Creates the FilterSecurityInterceptor
	 *
	 * @param http the builder to use
	 * @param metadataSource the FilterInvocationSecurityMetadataSource to use
	 * @param authenticationManager the AuthenticationManager to use
	 * @return the FilterSecurityInterceptor
	 * @throws Exception
	 */
	private FilterSecurityInterceptor createFilterSecurityInterceptor(H http,
			FilterInvocationSecurityMetadataSource metadataSource,
			AuthenticationManager authenticationManager) throws Exception {
       // 创建最终要配置到安全构建器 http 的安全拦截过滤器 FilterSecurityInterceptor,
       // 所需要的各种属性都由该类定义的方法提供,这些方法有的由本类提供实现,有的需要由
       // 实现子类提供实现。
		FilterSecurityInterceptor securityInterceptor = new FilterSecurityInterceptor();
		securityInterceptor.setSecurityMetadataSource(metadataSource);
		securityInterceptor.setAccessDecisionManager(getAccessDecisionManager(http));
		securityInterceptor.setAuthenticationManager(authenticationManager);
		securityInterceptor.afterPropertiesSet();
		return securityInterceptor;
	}
}

参考文章

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值