文章目录
一、DelegatingFilterProxy
- 提示:
DelegatingFilterProxy extends GenericFilterBean
GenericFilterBean implements Filter, BeanNameAware, EnvironmentAware,
EnvironmentCapable, ServletContextAware, InitializingBean, DisposableBean
GenericFilterBean 是 Servlet-api 中filter的子类 并且实现了 InitializingBean
- GenericFilterBean
//这个是 GenericFilterBean 的内部方法
@Override
public void afterPropertiesSet() throws ServletException {
initFilterBean();
}
/**
* 这个使用模板设计模式 交给子类实现 而 DelegatingFilterProxy 正是其子类
*/
protected void initFilterBean() throws ServletException {
}
- DelegatingFilterProxy
@Override
protected void initFilterBean() throws ServletException {
synchronized (this.delegateMonitor) {
if (this.delegate == null) {
// If no target bean name specified, use filter name.
if (this.targetBeanName == null) {
//这个getFilterName 可以看一下下面的代码块
this.targetBeanName = getFilterName();
}
// Fetch Spring root application context and initialize the delegate early,
// if possible. If the root application context will be started after this
// filter proxy, we'll have to resort to lazy initialization.
WebApplicationContext wac = findWebApplicationContext();
if (wac != null) {
this.delegate = initDelegate(wac);
}
}
}
}
protected Filter initDelegate(WebApplicationContext wac) throws ServletException {
String targetBeanName = getTargetBeanName();
Assert.state(targetBeanName != null, "No target bean name set");
//这个targetBeanName 的具体值 取决于使用的安全框架 我们这里说的是SpringSecurity 默认的配置是 springSecurityFilterChain
//从Spring容器中 取出Filter的实现
Filter delegate = wac.getBean(targetBeanName, Filter.class);
if (isTargetFilterLifecycle()) {
delegate.init(getFilterConfig());
}
return delegate;
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
//DCL来初始化delegate
// Lazily initialize the delegate if necessary.
Filter delegateToUse = this.delegate;
if (delegateToUse == null) {
synchronized (this.delegateMonitor) {
delegateToUse = this.delegate;
if (delegateToUse == null) {
WebApplicationContext wac = findWebApplicationContext();
if (wac == null) {
throw new IllegalStateException("No WebApplicationContext found: " +
"no ContextLoaderListener or DispatcherServlet registered?");
}
delegateToUse = initDelegate(wac);
}
this.delegate = delegateToUse;
}
}
//这个地方就是代理了 DelegatingFilterProxy 代理Filter ,Filter的实现类已经交给了Spring容器管理,通过 DelegatingFilterProxy 来将Filter产生关联。
// Let the delegate perform the actual doFilter operation.
invokeDelegate(delegateToUse, request, response, filterChain);
}
protected void invokeDelegate(
Filter delegate, ServletRequest request, ServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
delegate.doFilter(request, response, filterChain);
}
// 这个getFilterName 的代码块
@Nullable
protected String getFilterName() {
//意思就是有配置从配置中取没有配置就用beanName
//其实SpringSecurity就是用的BeanName 稍后我们贴代码
return (this.filterConfig != null ? this.filterConfig.getFilterName() : this.beanName);
}
到这我们只要理解
DelegatingFilterProxy是 SpringWeb模块的一个代理,为了能够更好的解耦以便于集成非Spring Security的其他安全框架,并且将由Spring容器管理的Filter实现类给代理了。
二、SpringSecurity
1、 WebSecurityConfigurerAdapter
我们通过自定义类来实现WebSecurityConfigurerAdapter 进行拓展 如: WebSecurityConfigurerImpl extends WebSecurityConfigurerAdapter。并 通过 @EnableWebSecurity 来启用SpringSecurity
跟进该注解我们可以找到 WebSecurityConfiguration见下面代码块:
- WebSecurityConfiguration
public static final String DEFAULT_FILTER_NAME = "springSecurityFilterChain";
//注意这个地方使用@Bean注解注入了springSecurityFilterChain 这个bean 该Bean的实现类是FilterChainProxy
//这样 在一 中我们在Spring容器中获取springSecurityFilterChain这个bean的时候就得到了FilterChainProxy的实例。
@Bean(name = AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME)
public Filter springSecurityFilterChain() throws Exception {
boolean hasConfigurers = this.webSecurityConfigurers != null && !this.webSecurityConfigurers.isEmpty();
boolean hasFilterChain = !this.securityFilterChains.isEmpty();
Assert.state(!(hasConfigurers && hasFilterChain),
"Found WebSecurityConfigurerAdapter as well as SecurityFilterChain. Please select just one.");
if (!hasConfigurers &&