SpringSecurity配置源码分析

Spring security框架简介

 -Spring Security 的前身是 Acegi Security ,是 Spring 项目组中用来提供安全认证服务的框架。

-Spring Security一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方式的安全框架,应用的安全性包括用户认证(Authentication)和用户授权(Authorization)两个部分。
-Spring Security对Web安全性的支持大量地依赖于Servlet过滤器。这些过滤器拦截进入请求,并且在应用程序处理该请求之前进行某些安全处理。
-Spring Security提供有若干个过滤器,它们能够拦截Servlet请求,并将这些请求转给认证和访问决策管理器处理,从而增强安全性。
-根据自己的需要,可以使用适当的过滤器来保护自己的应用程序。如果使用过Servlet过滤器且令其正常工作,就必须在Web应用程序的web.xml文件中使用 和元素配置它们。虽然这样做能起作用,但是它并不适用于使用依赖注入进行的配置。
1 在web.xml文件中配置
-为什么DelegatingFilterProxy的filter-name必须是springSecurityFilterChain?

<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>

-DelegatingFilterProxy并不是真正的Filter,在其initFilterBean方法中会从WebApplicationContext根据delegate
来获取到

@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) {
					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);
				}
			}
		}
	}

-在上面这代码中this.targetBeanName=getFilterName()就是获取名称叫做springSecurityFilterChain
通过在doFilter中发现真正干活的其实是delegate这个Filter,而delegate其实就是FilterChainProxy

@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
			throws ServletException, IOException {

		// 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;
			}
		}

		// Let the delegate perform the actual doFilter operation.
		invokeDelegate(delegateToUse, request, response, filterChain);
	}

-FilterChainProxy是spring在解析配置文件时装配到上下文中,并且beanName为springSecurityFilterChain, 因此在web.xml中需要配置filter-name为springSecurityFilterChain
2.在spring-security.xml文件中配置
-在配置文件中主要使用标签来过多成配置

<!-- 配置不拦截的资源 -->
    <security:http pattern="/login.jsp" security="none"/>
    <security:http pattern="/failer.jsp" security="none"/>
    <security:http pattern="/css/**" security="none"/>
    <security:http pattern="/img/**" security="none"/>
    <security:http pattern="/plugins/**" security="none"/>
    
	<security:http auto-config="true" use-expressions="false">
        <!-- 配置具体的拦截的规则 pattern="请求路径的规则" access="访问系统的人,必须有ROLE_USER和ROLE_ADMIN的角色" -->
        <security:intercept-url pattern="/**" access="ROLE_USER,ROLE_ADMIN"/>

        <!-- 定义跳转的具体的页面 -->
        <security:form-login
                login-page="/login.jsp"
                login-processing-url="/login.do"
                default-target-url="/index.jsp"
                authentication-failure-url="/failer.jsp"
                authentication-success-forward-url="/pages/main.jsp"
        />
    </security:http>

http标签是自定义标签,可以在spring-security-config包中查看

http\://www.springframework.org/schema/security=org.springframework.security.config.SecurityName spaceHandler

继续查看SecurityNamespaceHandler类,在其init方法

public void init() {
		loadParsers();
	}

在loadParsers()方法中,指定由HttpSecurityBeanDefinitionParser进行解析

parsers.put(Elements.HTTP, new HttpSecurityBeanDefinitionParser());

在HttpSecurityBeanDefinitionParser完成具体解析的parse方法中

registerFilterChainProxyIfNecessary(pc, pc.extractSource(element));

-这里就是注册了名为springSecurityFilterChain的filterChainProxy类
接下再看一下注册一系列Filter的地方createFilterChain,在这个方法中重点关注

/**
	 * Creates the {@code SecurityFilterChain} bean from an &lt;http&gt; element.
	 */
		AuthenticationConfigBuilder authBldr = new AuthenticationConfigBuilder(element,
				forceAutoConfig, pc, httpBldr.getSessionCreationPolicy(),
				httpBldr.getRequestCache(), authenticationManager,
				httpBldr.getSessionStrategy(), portMapper, portResolver,
				httpBldr.getCsrfLogoutHandler());

查看AuthenticationConfigBuilder创建代码

public AuthenticationConfigBuilder(Element element, boolean forceAutoConfig,
			ParserContext pc, SessionCreationPolicy sessionPolicy,
			BeanReference requestCache, BeanReference authenticationManager,
			BeanReference sessionStrategy, BeanReference portMapper,
			BeanReference portResolver, BeanMetadataElement csrfLogoutHandler) {
		this.httpElt = element;
		this.pc = pc;
		this.requestCache = requestCache;
		autoConfig = forceAutoConfig
				| "true".equals(element.getAttribute(ATT_AUTO_CONFIG));
		this.allowSessionCreation = sessionPolicy != SessionCreationPolicy.NEVER
				&& sessionPolicy != SessionCreationPolicy.STATELESS;
		this.portMapper = portMapper;
		this.portResolver = portResolver;
		this.csrfLogoutHandler = csrfLogoutHandler;

		createAnonymousFilter();
		createRememberMeFilter(authenticationManager);
		createBasicFilter(authenticationManager);
		createFormLoginFilter(sessionStrategy, authenticationManager);
		createOpenIDLoginFilter(sessionStrategy, authenticationManager);
		createX509Filter(authenticationManager);
		createJeeFilter(authenticationManager);
		createLogoutFilter();
		createLoginPageFilterIfNeeded();
		createUserDetailsServiceFactory();
		createExceptionTranslationFilter();

	}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值