Spring Security(Acegi)实现原理与应用一

1.引言:Spring  Security 是前身Acegi经过演变形成。主要是为咱们提供安全服务,主要包含验证,授权俩方面。

2.Spring  Security  实现原理和基本的过程,为了理解起来方便:先写我们较熟悉的场景——用户登陆-> 用户授权。

1)首先配置一个过滤器,很容易理解,我们web容器在开始操作前都会经过filter(实际上spring以DelegatingFilterProxy为入口,这个类里面存储了FilterChainProxy实例,至于说这些是什么意思我们向下看)

    
	
        mySpringSecurityFilterChain
		cn.com.nuskin.agelocme.config.DelegatingFilter
    

    
      springSecurityFilterChain
      /*
    

public class DelegatingFilter extends DelegatingFilterProxy{
	@Override
	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain filterChain) throws ServletException, IOException {
		
			
		HttpServletRequest httpRequest=(HttpServletRequest)request;

		String url = httpRequest.getRequestURI();
		if (url.indexOf("admin") != -1){
			
			super.doFilter(request, response, filterChain);
			return;
		}else{
			
			super.doFilter(request, response, filterChain);
		}
	}
	

我们可以看到 这样我们是做了准备工作.关注一下DelegatingFilterProxy这个类,我们可以在配置文件里直接使用该类,不用重新继承,这样做就是为了拓展.

DelegatingFilterProxy类继承于抽象类GenericFilterBean,间接地implement 了javax.servlet.Filter接口,Servlet容器在启动时,首先会调用Filter的i nit方法。GenericFilterBean实现了filter那么我们看init方法里做了什么。

 

	@Override
	public final void init(FilterConfig filterConfig) throws ServletException {
		Assert.notNull(filterConfig, "FilterConfig must not be null");
		if (logger.isDebugEnabled()) {
			logger.debug("Initializing filter '" + filterConfig.getFilterName() + "'");
		}

		this.filterConfig = filterConfig;

		// Set bean properties from init parameters.
		try {
			PropertyValues pvs = new FilterConfigPropertyValues(filterConfig, this.requiredProperties);
			BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);
			ResourceLoader resourceLoader = new ServletContextResourceLoader(filterConfig.getServletContext());
			bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, this.environment));
			initBeanWrapper(bw);
			bw.setPropertyValues(pvs, true);
		}
		catch (BeansException ex) {
			String msg = "Failed to set bean properties on filter '" +
				filterConfig.getFilterName() + "': " + ex.getMessage();
			logger.error(msg, ex);
			throw new NestedServletException(msg, ex);
		}

		// Let subclasses do whatever initialization they like.
		initFilterBean();

		if (logger.isDebugEnabled()) {
			logger.debug("Filter '" + filterConfig.getFilterName() + "' configured successfully");
		}
	}

看着红色部分,init方法设置了一些参数信息后调用initFilterBean来初始化filterBean该方法其实留给了子类来实现。这里其实就是我们的DelegatingFilterProxy initFilterBean方法。

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

意思很好理解如果我们配置了targetBeanName那么我们就会去加载这个配置的filter,否则就是我们的targetBeanName就是springSecurityFilterChain(该名称spring里已经默认好spring org.springframework.security.FilterChainProxy实例的名称)。此处我们并没有设置这个参数的值那么就会取到默认的值。

然后最终通过initDelegate方法获取了我们的filter实例同时设置到了DelegatingFilterProxy类的delegate属性里。实例org.springframework.security.FilterChainProxy(该类也是继承了GenericFilterBean)。最后通过DelegatingFilterProxy invokeDelegate(delegateToUse, request, response, filterChain)方法响应处理请求。

总结:这里主要有俩个filter一个代理类DelegatingFilterProxy 一个实际起作用spring org.springframework.security.FilterChainProxy该过滤器。这样

使得FilterChainProxy 被代理了在DelegatingFilterProxy 下。这样做的好处是FilterChainProxy 独立出来可以动态配置,可以是默认的spring提供,也可以根据

根据targetBeanName来自定义过滤器,一般情况下我们就默认。下面就是来说们为什么 FilterChainProxy 如何配置,怎么就通过initDelegate方法获取到了实例了?

2)FilterChainProxy配置和原理

首先看一下initDelegate方法:

	protected Filter initDelegate(WebApplicationContext wac) throws ServletException {
		Filter delegate = wac.getBean(getTargetBeanName(), Filter.class);
		if (isTargetFilterLifecycle()) {
			delegate.init(getFilterConfig());
		}
		return delegate;
	}

关键点就在于getTargetBeanName方法。要想搞明白我们就得来说一下上文说到的security.xml,看个简单的



	
		
		
	


auto-config="true"属性,spring security就会自动配置好了过滤器链。其中原理可以参考:http://dead-knight.iteye.com/blog/1511389 博客。

那么我们说到的过滤连是什么意思呢,那么如何自定义?

     
          
              
                  
                  
                  
              
          
     

spring在加载配置文件 加载securityFilterChainProxy就会初始化该过滤链注意bean id 必须是securityFilterChainProxy因为我的web.xml  DelegatingFilter代理过滤器没有配置自定的filter默认的spring securityFilterChainProxy的过滤器,这里我们只是给他设置了一些自定义过滤连参数。这么多都是我们的前置配置。当然自己定义了实际的过滤器

例如:

 
            targetBeanName 
            myFilter         //自己过滤器的名字 
         
然后自己可以配置bean id =myFilter的bean即可。下面就是实际的认证授权了待续



你可能感兴趣的:(spring)