版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/andy_zhang2007/article/details/82313144
package org.springframework.security.config.annotation.web.configuration;
// 忽略 import 行
/**
* Spring Security 的配置类 :
* 1. 使用一个 WebSecurity 对象创建执行 Spring Security 基于web的安全任务的 FilterChainProxy 对象。
* 2. 也会暴露一些必要的 bean。
* 3. 如何定制 Spring security 的web 安全,也就是 WebSecurity 对象 ?
* 3.1 实现一个继承自 WebSecurityConfigurerAdapter 的配置类 ,
* 3.2 或者 提供一个配置类,实现了接口 WebSecurityConfigurer
* 该配置类的配置会在使用 @EnableWebSecurity 时应用到系统。
*
* Uses a WebSecurity to create the FilterChainProxy that performs the web based security
* for Spring Security. It then exports the necessary beans. Customizations can be made to
* WebSecurity by extending WebSecurityConfigurerAdapter and exposing it as a Configuration
* or implementing WebSecurityConfigurer and exposing it as a Configuration. This configuration
* is imported when using EnableWebSecurity.
*
* @see EnableWebSecurity
* @see WebSecurity
*
* @author Rob Winch
* @author Keesun Baik
* @since 3.2
*/
@Configuration
public class WebSecurityConfiguration implements ImportAware, BeanClassLoaderAware {
private WebSecurity webSecurity;
// 是否启用了调试模式,来自注解 @EnableWebSecurity 的属性 debug,缺省值 false
private Boolean debugEnabled;
private List<SecurityConfigurer<Filter, WebSecurity>> webSecurityConfigurers;
private ClassLoader beanClassLoader;
@Autowired(required = false)
private ObjectPostProcessor<Object> objectObjectPostProcessor;
@Bean
public static DelegatingApplicationListener delegatingApplicationListener() {
return new DelegatingApplicationListener();
}
// 定义一个bean,是表达式处理器,缺省为一个 DefaultWebSecurityExpressionHandler,
// 仅在bean springSecurityFilterChain 被定义时才生效
@Bean
@DependsOn(AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME)
public SecurityExpressionHandler<FilterInvocation> webSecurityExpressionHandler() {
return webSecurity.getExpressionHandler();
}
/**
* Creates the Spring Security Filter Chain
* 定义 Spring Security Filter Chain , 名字为 springSecurityFilterChain
* @return
* @throws Exception
*/
@Bean(name = AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME)
public Filter springSecurityFilterChain() throws Exception {
boolean hasConfigurers = webSecurityConfigurers != null
&& !webSecurityConfigurers.isEmpty();
if (!hasConfigurers) {
// 如果没有 webSecurityConfigurer, 则提供一个却省的
WebSecurityConfigurerAdapter adapter = objectObjectPostProcessor
.postProcess(new WebSecurityConfigurerAdapter() {
});
webSecurity.apply(adapter);
}
// 根据配置构建 Filter FilterChainProxy 并返回之
return webSecurity.build();
}
// 定义一个bean,是web调用权限评估器,用于判断一个用户是否可以访问某个URL,
// 对于 JSP tag 支持必要。 仅在bean springSecurityFilterChain 被定义时才生效。
/**
* Creates the WebInvocationPrivilegeEvaluator that is necessary for the JSP
* tag support.
* @return the WebInvocationPrivilegeEvaluator
* @throws Exception
*/
@Bean
@DependsOn(AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME)
public WebInvocationPrivilegeEvaluator privilegeEvaluator() throws Exception {
return webSecurity.getPrivilegeEvaluator();
}
/**
* Sets the <SecurityConfigurer<FilterChainProxy, WebSecurityBuilder>
* instances used to create the web configuration.
*
* @param objectPostProcessor the ObjectPostProcessor used to create a
* WebSecurity instance
* @param webSecurityConfigurers the
* <SecurityConfigurer<FilterChainProxy, WebSecurityBuilder> instances used to
* create the web configuration
* @throws Exception
*/
@Autowired(required = false)
public void setFilterChainProxySecurityConfigurer(
ObjectPostProcessor<Object> objectPostProcessor,
@Value("#{@autowiredWebSecurityConfigurersIgnoreParents.getWebSecurityConfigurers()}") List<SecurityConfigurer<Filter, WebSecurity>> webSecurityConfigurers)
throws Exception {
webSecurity = objectPostProcessor
.postProcess(new WebSecurity(objectPostProcessor));
if (debugEnabled != null) {
webSecurity.debug(debugEnabled);
}
Collections.sort(webSecurityConfigurers, 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) {
webSecurity.apply(webSecurityConfigurer);
}
this.webSecurityConfigurers = webSecurityConfigurers;
}
@Bean
public AutowiredWebSecurityConfigurersIgnoreParents autowiredWebSecurityConfigurersIgnoreParents(
ConfigurableListableBeanFactory beanFactory) {
return new AutowiredWebSecurityConfigurersIgnoreParents(beanFactory);
}
/**
* A custom verision of the Spring provided AnnotationAwareOrderComparator that uses
* AnnotationUtils#findAnnotation(Class, Class) to look on super class
* instances for the 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;
}
}
/*
* 获取导入该配置bean的配置bean上的注解元数据并设置到该配置bean
* 这里主要是为了获取注解 @EnableWebSecurity 的属性 debugEnabled
*
* @see org.springframework.context.annotation.ImportAware#setImportMetadata(org.
* springframework.core.type.AnnotationMetadata)
*/
public void setImportMetadata(AnnotationMetadata importMetadata) {
Map<String, Object> enableWebSecurityAttrMap = importMetadata
.getAnnotationAttributes(EnableWebSecurity.class.getName());
AnnotationAttributes enableWebSecurityAttrs = AnnotationAttributes
.fromMap(enableWebSecurityAttrMap);
debugEnabled = enableWebSecurityAttrs.getBoolean("debug");
if (webSecurity != null) {
webSecurity.debug(debugEnabled);
}
}
/*
*
*
* @see
* org.springframework.beans.factory.BeanClassLoaderAware#setBeanClassLoader(java.
* lang.ClassLoader)
*/
public void setBeanClassLoader(ClassLoader classLoader) {
this.beanClassLoader = classLoader;
}
}