Spring学习笔记12

来源:互联网 发布:mac粉底液色号怎么选 编辑:程序博客网 时间:2024/06/05 08:26

Web应用安全

SpringWeb安全主要依靠servlet过滤器(servlet filter)filter过滤器会在应用处理请求之前拦截下请求并传递给验证管理器和访问决策管理器。Spring提供了一组(17)servlet过滤器供开发人员使用,但一般只需用到其中的一些即可。特别地,当一个请求被提交给应用时,至少会经过以下4filter

·Integration filter:因为HTTP是无状态的,所以Spring需要保存请求中用户的验证信息。Integration filter就被用来在请求开始之前获取先前保存的验证信息(多保存在HTTP会话中),这样Spring的其他filter就可以工作了。

·Authentication-processing filter:它将确定一个请求是否是一个验证请求。如果是,它将获取用户信息(用户名,密码)并传递给验证管理器做用户身份验证。如果不是验证请求,它不会执行任何处理只是将请求传递给下一个filter

·Exception Translation filter:它的唯一工作就是将AccessDeniedExceptionAuthenticationException异常转化成HTTP响应信息。如果检测到AuthenticationException异常,请求将被发送到某个验证入口点(如登陆界面);如果检测到AccessDeniedException异常,HTTP403错误将被返回给浏览器。

·Filter Security Interceptor:扮演着安全拦截者的角色,用于确定用户是否有足够权限访问资源。事实上,它依赖于验证管理器和决策管理器来进行权限的授予或限制。

       如果用户通过了Filter Security Inteceptor,用户就可以访问web资源,否则会抛出AccessDeniedException异常。***********

1.     filter代理

注入依赖并不适用于filter的配置。比如下面的代码:

<filter>

     <filter-name>Foo</filter-name>

       <filter-class>FooFilter</filter-class>

</filter>

如果现在FooFilter要引用Bar对象,你如何将一个Bar的实例注入FooFilter?答案是不能。web.xml没有依赖注入的概念,Spring也没有一个直接的方法把一个bean注入到一个servlet filter中。你只能使用WebApplicationContextUtils类来获取bar对象,例如:

ApplicationContextctx = WebApplicationContextUtils.

                     getWebApplicationContext(servletContext);

Barbar = (Bar) ctx.getBean("bar");

但是这有两个问题:第一,你必须把和Spring相关的代码嵌入servlet过滤器中;第二,你必须要硬编码实现bar bean的引用。基于此,你需要使用FilterToBeanProxy

·代理servlet过滤器

FilterToBeanProxy是一个特殊的servlet filter。它本身不会做任何事情,只是将它的工作代理给Spring上下文环境中的一个bean来实现。这个委托bean和其他filter一样实现了Filter接口,并且配置在Spring的配置文件中而不是web.xml中。

     你可以在Spring中使用FilterToBeanProxy来配置真正的filter。原来的web.xml文件中只有<filter>标签,但在Spring的配置文件中你可以配置真正的FooFilterweb.xml文件中的配置方法如下:

<filter>

     <filter-name>Foo</filter-name>

     <filter-class>org.acegisecurity.util.FilterToBeanProxy</filter-class>

     <init-param>

            <param-name>targetClass</param-name>

            <param-value>com.roadrantz.FooFilter</param-value>

     </init-param>

</filter>

这里的targetClass初始化参数被设置成FooFilter的完整路径。当初始化FilterToBeanProxy之后,它会在Spring context中查找类型为FooFilterbean,然后FilterToBeanProxy会委托给FooFilter bean

<bean id=”fooFilter” class=”com.raodrantz.FooFilter”>

     <propertyname=”bar” ref=”bar” />

</bean>

如果没有找到FooFilter将会抛出一个异常。如果找到多个,只会使用第一个。当然,你可以设置targetBean的初始化参数来选择特定的bean,例如:

<filter>

     <filter-name>Foo</filter-name>

     <filter-class>….util.FilterToBeanProxy</filter-class>

     <init-param>

            <param-name>targetBean</param-name>

            <param-value>fooFilter</param-value>

     </init-param>

</filter>

targetBean初始化参数可以让你指定要委托的bean,但是你需要保证委托beanweb.xmlSpring配置文件中严格保持一致。这样不利于我们修改bean的名字。因此,我们还是使用targetClass

     最后,你需要把一个filter链接到一个URL模式上,例如:

<filter-mapping>

     <filter-name>Foo</filter-name>

     <url-pattern>/*</url-pattern>

</filter-mapping>

无论你使用targetClass还是targetBeanSpring都使用ContextLoaderListenerContextLoaderServlet来加载context

     如前所述,Spring使用servlet filter来保证web安全。每个filter都要被注入到其他bean中。

·代理多个filter

     实际上,FilterToBean代理的bean可以是任何一个实现了javax.servlet.Filter接口的类,它可以是Springfilter,也可以是你自己创建的filter。如前所述,如果使用Springfilter,你需要配置至少4filter。当然这并不意味着你要为每个Spring Security filter配置一个FilterToBeanProxySpring提供了FilterChainProxy来解决这个问题。

     FilterChainProxy实现了Filter接口。我们配置它来串联多个filter,如图:*******


     FilterToBeanProxy截获客户端的请求并发送给FilterChainProxy,然后FilterChainProxy负责分发给多个配置好的filter。配置方法如下:

<bean id=”filterChainProxy”

     class=”org.acegisecurity.util.FilterChainProxy”>

     <propertyname=”filterInvocationDefinitionSource”>

            <value>

                   CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON

                   PATTERN_TYPE_APACHE_ANT

                   /**=filter1,filter2, filter3

            </value>

     </property>

</bean>

value标签中的第一行表示使用一个合法的URL并将其小写化,第二行表示使用ApacheAnt风格的路径表示法,最后一行的/**表示匹配所有的URLfilter1filter2filter3是三个配置好的filter。它们将按顺序接受request,并以反序顺序返回response

·Spring安全配置代理
现在我们开始配置在web.xmlfilter代理,

<filter>

       <filter-name>SpringSecurity Filter Chain Proxy</filter-name>

       <filter-class>org.acegisecurity.util.FilterToBeanProxy</filter-class>

       <init-param>

              <param-name>targetClass</param-name>

              <param-value>org.acegesecurity.util.FilterChainProxy</param-value>

       </init-param>

</filter>

这里配置FilterToBeanProxy来代理Spring中类型为FilterChainProxy的任意bean,而FilterChainProxy我们先前已经在Spring context中配置过了。在web.xml中我们还需要为FilterToBeanProxy配置一个filter映射:

<filter-mapping>

       <filter-name>SpringSecurity Filter Chain Proxy</filter-name>

       <url-pattern>/*</url-pattern>

</filter-mapping>

filter-mapping标签中filter-name的值必须匹配filter标签中的filter-name值。另外,我们推荐使用/*,这样所有的request都可以被传递到Spring Security。这样更简单一些。在后面配置FilterSecurityInterceptor时就可以选择哪些部分需要安全保护哪些不需要。

       现在为止web.xml的配置工作就结束了——只需要配置一个FilterToBeanProxy即可。下面我们开始着手配置Spring context

       我们需要一个FilterChainProxy bean来处理FilterToBeanProxy传递过来的request。对于RoadRantz应用来说,先从在roadrantz-security.xml中配置FilterChainProxy开始:

<bean id=”filterChainProxy” class=”….FilterChainProxy”>

       <property name=”filterInvocationDefinitionSource”>

              <value>

                     CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON

                     PATTERN_TYPE_APACHE_ANT

                     /**=httpSessionIntegrationFilter,

                            authenticationProcessingFilter,

                            exceptionTranslationFilter,

                            filterSecurityInterceptor

              </value>

       </property>

</bean>

这里配置了FilterChainProxy来串联四个Springfilter。重要的是Springfilter需要按照filterInvocationDefinitionSource属性中的顺序来配置。因为某些filter会认为有些任务是在它之前执行的。每一个filterInvocationDefinitionSource中配置的filter都引用了Spring应用上下文中的一个bean