SpringSecurity6从入门到上天系列第五篇:详解SpringSecurity6中的Security Filters的作用和原理以及默认的15个核心Security Filters

该文章已生成可运行项目,

福利发送:

        1:你想彻底搞明白SpringSecurity么?你想对SpringSecurity6进行源码级别的学习么?

        2:你想彻底掌握Spring的应用和源码,在面试的时候吊打面试官么?

        那欢迎你加入suns 孙哥的企鹅QQ 3群:583783824

        在这里你可以找到志同道合的朋友,还有大神孙哥作为你的领路人。在这里,不仅仅是SpringSecurity更让你在Mybatis、Netty、Rpc、Dubbo、SpringCloud、Docker和k8s....等等技术领域发生翻天覆地的变化。

        以上所有,在群里都有我们免费的视频和笔记资料呦~~~

        欢迎进群领取,期待你的加入!

文章目录

前言

1:知识回顾

2:运行图回顾

一: Security Filters

1:概述

2:Spring Security默认过滤器

二:关键BeanFilter

1:DisableEncoderUrlFilter

2:WebAsynManagerIntegrationFilter

3:SecurityContextHolderFilter

4:HeaderWriterFilter

5:CsrfFilter

6:LogoutFilter

7:UsernamePasswordAuthenticationFilter

8:DefaultLoginPageGeneratingFilter

9:DefaultLogoutPageGeneratingFilter

10:BasicAuthenticationFilter

11:RequestCacheAwareFilter

12:SecurityContextHolderAwareRequestFilter

13:AnonymousAuthenticationFilter

14:ExceptionTranslationFilter

15:AuthorizationFilter


大神链接:作者有幸结识技术大神孙哥为好友,获益匪浅。现在把孙哥视频分享给大家。

孙哥链接:孙哥个人主页
作者简介:一个颜值99分,只比孙哥差一点的程序员
本专栏简介:话不多说,让我们一起干翻SpringSecurity6

本文章简介:话不多说,让我们讲清楚SpringSecurity6中的Security Filters的作用和原理以及默认的15个核心Security Filters

前言

1:知识回顾

       DelegatingFilterProxy 它的作用就是:实现把 servlet容器中的 Filter 同 Spring 容器中的 bean 关联起来,DelegatingFilterProxy实现了Filter接口,Servlet容器启动就会加载好这个类。借助他可以实现普通的Filter拦截到的Http请求交由FilterChainProxy

        FilterChainProxy把 SecurityFilterChain 嵌入到 Web项目的原生过滤器链中DelegatingFilterProxy 把 FilterChainProxy 整合到原生的过滤器链中

        FilterChainProxy 是顶层管理者,统一管理 Security Filter和 SecurityFllterChain过滤器链

        当请求到达 FilterChainProxy 时,会根据当前请求匹配SecurityFilterChain,然后将请求依次转发给 SecurityFilterChain 中的 Security Filter

2:运行图回顾

一: Security Filters

1:概述

         Spring Security 中最终对请求进行处理的就是某个 SecurityFilterChain 中的 Security Filter,这些Filter都设置为 Bean并且注入到 Spring容器中,且会按照先后顺序执行。

        下面展示 Spring Security 中给我们提供的过滤器,以及默认情况下会被加载的过滤器

2:Spring Security默认过滤器

         FilterOrderRegistration这个在构造函数中按照顺序,put了一个又一个的BeanFilter或者叫Security Filter

    FilterOrderRegistration() {
        Step order = new Step(100, 100);
        this.put(DisableEncodeUrlFilter.class, order.next());
        this.put(ForceEagerSessionCreationFilter.class, order.next());
        this.put(ChannelProcessingFilter.class, order.next());
        order.next();
        this.put(WebAsyncManagerIntegrationFilter.class, order.next());
        this.put(SecurityContextHolderFilter.class, order.next());
        this.put(SecurityContextPersistenceFilter.class, order.next());
        this.put(HeaderWriterFilter.class, order.next());
        this.put(CorsFilter.class, order.next());
        this.put(CsrfFilter.class, order.next());
        this.put(LogoutFilter.class, order.next());
        this.filterToOrder.put("org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestRedirectFilter", order.next());
        this.filterToOrder.put("org.springframework.security.saml2.provider.service.web.Saml2WebSsoAuthenticationRequestFilter", order.next());
        this.put(X509AuthenticationFilter.class, order.next());
        this.put(AbstractPreAuthenticatedProcessingFilter.class, order.next());
        this.filterToOrder.put("org.springframework.security.cas.web.CasAuthenticationFilter", order.next());
        this.filterToOrder.put("org.springframework.security.oauth2.client.web.OAuth2LoginAuthenticationFilter", order.next());
        this.filterToOrder.put("org.springframework.security.saml2.provider.service.web.authentication.Saml2WebSsoAuthenticationFilter", order.next());
        this.put(UsernamePasswordAuthenticationFilter.class, order.next());
        order.next();
        this.put(DefaultLoginPageGeneratingFilter.class, order.next());
        this.put(DefaultLogoutPageGeneratingFilter.class, order.next());
        this.put(ConcurrentSessionFilter.class, order.next());
        this.put(DigestAuthenticationFilter.class, order.next());
        this.filterToOrder.put("org.springframework.security.oauth2.server.resource.web.authentication.BearerTokenAuthenticationFilter", order.next());
        this.put(BasicAuthenticationFilter.class, order.next());
        this.put(RequestCacheAwareFilter.class, order.next());
        this.put(SecurityContextHolderAwareRequestFilter.class, order.next());
        this.put(JaasApiIntegrationFilter.class, order.next());
        this.put(RememberMeAuthenticationFilter.class, order.next());
        this.put(AnonymousAuthenticationFilter.class, order.next());
        this.filterToOrder.put("org.springframework.security.oauth2.client.web.OAuth2AuthorizationCodeGrantFilter", order.next());
        this.put(SessionManagementFilter.class, order.next());
        this.put(ExceptionTranslationFilter.class, order.next());
        this.put(FilterSecurityInterceptor.class, order.next());
        this.put(AuthorizationFilter.class, order.next());
        this.put(SwitchUserFilter.class, order.next());
    }

        在SpringSecurity中默认的这些默认过滤器有很多,我们接下来找关键的一起看一下。

二:关键BeanFilter

        接下来我们介绍的这几款Bean Filter都是默认程序启动就加载的。

1:DisableEncoderUrlFilter

        禁止URL重新编码,默认程序启动就会加载。

2:WebAsynManagerIntegrationFilter

        将WebAsyncManager与SpringSecurity上下文进行集成。默认程序启动就会加载。

        将web的异步处理管理器与SpringSecurity上下文进行集成

3:SecurityContextHolderFilter

        获取安全上下文,默认程序启动就会加载。

4:HeaderWriterFilter

        处理头信息加入响应中,默认程序启动就会加载。

5:CsrfFilter

        处理CSRF攻击,默认程序启动就会加载。

6:LogoutFilter

        处理注销登录,默认程序启动就会加载。

7:UsernamePasswordAuthenticationFilter

        处理表单登录,默认程序启动就会加载。

8:DefaultLoginPageGeneratingFilter

        配置默认登录页面,默认程序启动就会加载。

9:DefaultLogoutPageGeneratingFilter

        配置默认注销页面,默认程序启动就会加载。

10:BasicAuthenticationFilter

        处理 HttpBasic登录,默认程序启动就会加载。

11:RequestCacheAwareFilter

        处理请求缓存,默认程序启动就会加载。

12:SecurityContextHolderAwareRequestFilter

        包装原始请求,默认程序启动就会加载。

13:AnonymousAuthenticationFilter

        配置匿名认证,默认程序启动就会加载。

14:ExceptionTranslationFilter

        处理认证/授权中的异常,默认程序启动就会加载。

15:AuthorizationFilter

        处理当前用户是否有权限访问目标资源,默认程序启动就会加载。

        Spring Security 提供了30 多个过滤器。默认情况下Spring Boot 在对 Spring Security 进入自动化配置时,会创建一个名为 SpringSecurityFilerChain 的过滤器,并注入到 Spring 容器中,这个过滤器将负责所有的安全管理,包括用户认证、授权、重定向到登录页面等。具体可以参考WebSecurityConfiguration的源码:

public final class DefaultSecurityFilterChain implements SecurityFilterChain {
    private static final Log logger = LogFactory.getLog(DefaultSecurityFilterChain.class);
    private final RequestMatcher requestMatcher;
    private final List<Filter> filters;

    public DefaultSecurityFilterChain(RequestMatcher requestMatcher, Filter... filters) {
        this(requestMatcher, Arrays.asList(filters));
    }

    public DefaultSecurityFilterChain(RequestMatcher requestMatcher, List<Filter> filters) {
        if (filters.isEmpty()) {
            logger.info(LogMessage.format("Will not secure %s", requestMatcher));
        } else {
            logger.info(LogMessage.format("Will secure %s with %s", requestMatcher, filters));
        }

        this.requestMatcher = requestMatcher;
        this.filters = new ArrayList(filters);
    }

    public RequestMatcher getRequestMatcher() {
        return this.requestMatcher;
    }

    public List<Filter> getFilters() {
        return this.filters;
    }

    public boolean matches(HttpServletRequest request) {
        return this.requestMatcher.matches(request);
    }

    public String toString() {
        String var10000 = this.getClass().getSimpleName();
        return var10000 + " [RequestMatcher=" + this.requestMatcher + ", Filters=" + this.filters + "]";
    }
}
@Configuration(proxyBeanMethods = false)
public class WebSecurityConfiguration implements ImportAware, BeanClassLoaderAware {

	private WebSecurity webSecurity;

	private Boolean debugEnabled;

	private List<SecurityConfigurer<Filter, WebSecurity>> webSecurityConfigurers;

	private List<SecurityFilterChain> securityFilterChains = Collections.emptyList();

	private List<WebSecurityCustomizer> webSecurityCustomizers = Collections.emptyList();

	private ClassLoader beanClassLoader;

	@Autowired(required = false)
	private ObjectPostProcessor<Object> objectObjectPostProcessor;

	@Autowired(required = false)
	private HttpSecurity httpSecurity;

	@Bean
	public static DelegatingApplicationListener delegatingApplicationListener() {
		return new DelegatingApplicationListener();
	}

	@Bean
	@DependsOn(AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME)
	public SecurityExpressionHandler<FilterInvocation> webSecurityExpressionHandler() {
		return this.webSecurity.getExpressionHandler();
	}

	/**
	 * Creates the Spring Security Filter Chain
	 * @return the {@link Filter} that represents the security filter chain
	 * @throws Exception
	 */
	@Bean(name = AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME)
	public Filter springSecurityFilterChain() throws Exception {
		boolean hasFilterChain = !this.securityFilterChains.isEmpty();
		if (!hasFilterChain) {
			this.webSecurity.addSecurityFilterChainBuilder(() -> {
				this.httpSecurity.authorizeHttpRequests((authorize) -> authorize.anyRequest().authenticated());
				this.httpSecurity.formLogin(Customizer.withDefaults());
				this.httpSecurity.httpBasic(Customizer.withDefaults());
				return this.httpSecurity.build();
			});
		}
		for (SecurityFilterChain securityFilterChain : this.securityFilterChains) {
			this.webSecurity.addSecurityFilterChainBuilder(() -> securityFilterChain);
		}
		for (WebSecurityCustomizer customizer : this.webSecurityCustomizers) {
			customizer.customize(this.webSecurity);
		}
		return this.webSecurity.build();
	}

	/**
	 * Creates the {@link WebInvocationPrivilegeEvaluator} that is necessary to evaluate
	 * privileges for a given web URI
	 * @return the {@link WebInvocationPrivilegeEvaluator}
	 */
	@Bean
	@DependsOn(AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME)
	public WebInvocationPrivilegeEvaluator privilegeEvaluator() {
		return this.webSecurity.getPrivilegeEvaluator();
	}

	/**
	 * Sets the {@code <SecurityConfigurer<FilterChainProxy, WebSecurityBuilder>}
	 * instances used to create the web configuration.
	 * @param objectPostProcessor the {@link ObjectPostProcessor} used to create a
	 * {@link WebSecurity} instance
	 * @param beanFactory the bean factory to use to retrieve the relevant
	 * {@code <SecurityConfigurer<FilterChainProxy, WebSecurityBuilder>} instances used to
	 * create the web configuration
	 * @throws Exception
	 */
	@Autowired(required = false)
	public void setFilterChainProxySecurityConfigurer(ObjectPostProcessor<Object> objectPostProcessor,
			ConfigurableListableBeanFactory beanFactory) throws Exception {
		this.webSecurity = objectPostProcessor.postProcess(new WebSecurity(objectPostProcessor));
		if (this.debugEnabled != null) {
			this.webSecurity.debug(this.debugEnabled);
		}
		List<SecurityConfigurer<Filter, WebSecurity>> webSecurityConfigurers = new AutowiredWebSecurityConfigurersIgnoreParents(
				beanFactory)
			.getWebSecurityConfigurers();
		webSecurityConfigurers.sort(AnnotationAwareOrderComparator.INSTANCE);
		Integer previousOrder = null;
		Object previousConfig = null;
		for (SecurityConfigurer<Filter, WebSecurity> config : webSecurityConfigurers) {
			Integer order = AnnotationAwareOrderComparator.lookupOrder(config);
			if (previousOrder != null && previousOrder.equals(order)) {
				throw new IllegalStateException("@Order on WebSecurityConfigurers must be unique. Order of " + order
						+ " was already used on " + previousConfig + ", so it cannot be used on " + config + " too.");
			}
			previousOrder = order;
			previousConfig = config;
		}
		for (SecurityConfigurer<Filter, WebSecurity> webSecurityConfigurer : webSecurityConfigurers) {
			this.webSecurity.apply(webSecurityConfigurer);
		}
		this.webSecurityConfigurers = webSecurityConfigurers;
	}

	@Autowired(required = false)
	void setFilterChains(List<SecurityFilterChain> securityFilterChains) {
		this.securityFilterChains = securityFilterChains;
	}

	@Autowired(required = false)
	void setWebSecurityCustomizers(List<WebSecurityCustomizer> webSecurityCustomizers) {
		this.webSecurityCustomizers = webSecurityCustomizers;
	}

	@Bean
	public static BeanFactoryPostProcessor conversionServicePostProcessor() {
		return new RsaKeyConversionServicePostProcessor();
	}

	@Override
	public void setImportMetadata(AnnotationMetadata importMetadata) {
		Map<String, Object> enableWebSecurityAttrMap = importMetadata
			.getAnnotationAttributes(EnableWebSecurity.class.getName());
		AnnotationAttributes enableWebSecurityAttrs = AnnotationAttributes.fromMap(enableWebSecurityAttrMap);
		this.debugEnabled = enableWebSecurityAttrs.getBoolean("debug");
		if (this.webSecurity != null) {
			this.webSecurity.debug(this.debugEnabled);
		}
	}

	@Override
	public void setBeanClassLoader(ClassLoader classLoader) {
		this.beanClassLoader = classLoader;
	}

	/**
	 * A custom version of the Spring provided AnnotationAwareOrderComparator that uses
	 * {@link AnnotationUtils#findAnnotation(Class, Class)} to look on super class
	 * instances for the {@link Order} annotation.
	 *
	 * @author Rob Winch
	 * @since 3.2
	 */
	private static class AnnotationAwareOrderComparator extends OrderComparator {

		private static final AnnotationAwareOrderComparator INSTANCE = new AnnotationAwareOrderComparator();

		@Override
		protected int getOrder(Object obj) {
			return lookupOrder(obj);
		}

		private static int lookupOrder(Object obj) {
			if (obj instanceof Ordered) {
				return ((Ordered) obj).getOrder();
			}
			if (obj != null) {
				Class<?> clazz = ((obj instanceof Class) ? (Class<?>) obj : obj.getClass());
				Order order = AnnotationUtils.findAnnotation(clazz, Order.class);
				if (order != null) {
					return order.value();
				}
			}
			return Ordered.LOWEST_PRECEDENCE;
		}

	}

}

本文章已经生成可运行项目
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

练拳百万陈平安

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值