Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架。它提供了一组可以在Spring应用上下文中配置的Bean,充分利用了Spring IoC,DI和AOP(面向切面编程)功能,为应用系统提供声明式的安全访问控制功能。
使用过spring-security的对下面的配置一定不会陌生,
1.web.xml相关配置
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
2.spring-security相关配置文件
<http use-expressions="true">
<intercept-url pattern="/anonymous*" access="isAnonymous()"/>
<intercept-url pattern="/login*" access="permitAll" requires-channel="https"/>
<intercept-url pattern="/perform_login" requires-channel="https"/>
<intercept-url pattern="/**" access="isAuthenticated()" requires-channel="http"/>
<csrf disabled="true"/>
<form-login login-page='/login.html' login-processing-url="/perform_login" default-target-url="/homepage.html" authentication-failure-url="/login.html?error=true"
always-use-default-target="true"/>
<logout logout-url="/perform_logout" delete-cookies="JSESSIONID" success-handler-ref="customLogoutSuccessHandler"/>
<session-management session-fixation-protection="none"/>
</http>
为什么在web.xml中会使用springSecurityFilterChain这个名字,这个名字又有什么由来呢?下面笔者就直入主题:
1.org.springframework.security.config.SecurityNamespaceHandler,该类负责解析spring-security的配置文件,下面看看这个类的parse方法:
public BeanDefinition parse(Element element, ParserContext pc) {
if (!namespaceMatchesVersion(element)) {
pc.getReaderContext().fatal("You cannot use a spring-security-2.0.xsd or spring-security-3.0.xsd schema " +
"with Spring Security 3.1. Please update your schema declarations to the 3.1 schema.", element);
}
String name = pc.getDelegate().getLocalName(element);
BeanDefinitionParser parser = parsers.get(name);
if (parser == null) {
// SEC-1455. Load parsers when required, not just on init().
loadParsers();
}
if (parser == null) {
if (Elements.HTTP.equals(name) || Elements.FILTER_SECURITY_METADATA_SOURCE.equals(name) ||
Elements.FILTER_CHAIN_MAP.equals(name) || Elements.FILTER_CHAIN.equals(name)) {
reportMissingWebClasses(name, pc, element);
} else {
reportUnsupportedNodeType(name, pc, element);
}
return null;
}
return parser.parse(element, pc); //parser为HttpSecurityBeanDefinitionParser类
}
2.接下来我们进入HttpSecurityBeanDefinitionParser类的parse方法,看下庐山真面目:
public BeanDefinition parse(Element element, ParserContext pc) {
CompositeComponentDefinition compositeDef =
new CompositeComponentDefinition(element.getTagName(), pc.extractSource(element));
pc.pushContainingComponent(compositeDef);
registerFilterChainProxyIfNecessary(pc, pc.extractSource(element));
// Obtain the filter chains and add the new chain to it
BeanDefinition listFactoryBean = pc.getRegistry().getBeanDefinition(BeanIds.FILTER_CHAINS);
List<BeanReference> filterChains = (List<BeanReference>)
listFactoryBean.getPropertyValues().getPropertyValue("sourceList").getValue();
filterChains.add(createFilterChain(element, pc));
pc.popAndRegisterContainingComponent();
return null;
}
3.看下HttpSecurityBeanDefinitionParser类的registerFilterChainProxyIfNecessary方法:
static void registerFilterChainProxyIfNecessary(ParserContext pc, Object source) {
if (pc.getRegistry().containsBeanDefinition(BeanIds.FILTER_CHAIN_PROXY)) {
return;
}
// Not already registered, so register the list of filter chains and the FilterChainProxy
BeanDefinition listFactoryBean = new RootBeanDefinition(ListFactoryBean.class);
listFactoryBean.getPropertyValues().add("sourceList", new ManagedList());
pc.registerBeanComponent(new BeanComponentDefinition(listFactoryBean, BeanIds.FILTER_CHAINS));
BeanDefinitionBuilder fcpBldr = BeanDefinitionBuilder.rootBeanDefinition(FilterChainProxy.class);
fcpBldr.getRawBeanDefinition().setSource(source);
fcpBldr.addConstructorArgReference(BeanIds.FILTER_CHAINS);
fcpBldr.addPropertyValue("filterChainValidator", new RootBeanDefinition(DefaultFilterChainValidator.class));
BeanDefinition fcpBean = fcpBldr.getBeanDefinition();
pc.registerBeanComponent(new BeanComponentDefinition(fcpBean, BeanIds.FILTER_CHAIN_PROXY));
pc.getRegistry().registerAlias(BeanIds.FILTER_CHAIN_PROXY, BeanIds.SPRING_SECURITY_FILTER_CHAIN);
//public static final String SPRING_SECURITY_FILTER_CHAIN = "springSecurityFilterChain";
}
4.有了上面的讲解,详细小伙伴应该知道springSecurityFilterChain这个别名的来历了