福利发送:
1:你想彻底搞明白SpringSecurity么?你想对SpringSecurity6进行源码级别的学习么?
2:你想彻底掌握Spring的应用和源码,在面试的时候吊打面试官么?
那欢迎你加入suns 孙哥的企鹅QQ 3群:583783824
在这里你可以找到志同道合的朋友,还有大神孙哥作为你的领路人。在这里,不仅仅是SpringSecurity更让你在Mybatis、Netty、Rpc、Dubbo、SpringCloud、Docker和k8s....等等技术领域发生翻天覆地的变化。
以上所有,在群里都有我们免费的视频和笔记资料呦~~~
欢迎进群领取,期待你的加入!
文章目录
2:WebAsynManagerIntegrationFilter
7:UsernamePasswordAuthenticationFilter
8:DefaultLoginPageGeneratingFilter
9:DefaultLogoutPageGeneratingFilter
12:SecurityContextHolderAwareRequestFilter
13:AnonymousAuthenticationFilter
大神链接:作者有幸结识技术大神孙哥为好友,获益匪浅。现在把孙哥视频分享给大家。
孙哥链接:孙哥个人主页
作者简介:一个颜值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;
}
}
}

8471

被折叠的 条评论
为什么被折叠?



