`
aasonwu
  • 浏览: 34499 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

Spring Security 自定义过滤链filters

阅读更多
  • spring security过滤链filter的顺序参考, 查看org.springframework.security.config.http.HttpSecurityBeanDefinitionParser.createFilterChain代码:
            //定义未排序filter集合。该集合中的对象为OrderDecorator实例。 
            List<OrderDecorator> unorderedFilterChain = new ArrayList<OrderDecorator>();
            //添加http、认证相关的filter集合
            unorderedFilterChain.addAll(httpBldr.getFilters());
            unorderedFilterChain.addAll(authBldr.getFilters());
            unorderedFilterChain.addAll(buildCustomFilterList(element, pc));
            //根据排序规则进行排序
            Collections.sort(unorderedFilterChain, new OrderComparator());
            //检查每个filter与前一个filter的位置是否相同  
            //这里的检查主要是防止自定义filter直接配置position属性,造成与默认的filter产生order冲突
            checkFilterChainOrder(unorderedFilterChain, pc, pc.extractSource(element));
    
            // The list of filter beans
            List<BeanMetadataElement> filterChain = new ManagedList<BeanMetadataElement>();
            //重新定义filterChain,把经过排序的filter依次添加到filterChain集合中
            for (OrderDecorator od : unorderedFilterChain) {
                filterChain.add(od.bean);
            }
    
            return createSecurityFilterChainBean(element, pc, filterChain);
     
  •         unorderedFilterChain.addAll(httpBldr.getFilters());
            unorderedFilterChain.addAll(authBldr.getFilters());
            unorderedFilterChain.addAll(buildCustomFilterList(element, pc));
     上述代码返回的过滤链已经是经过OrderDecorator类包装的带有过滤链order顺序属性的集合。
  • Collections.sort(unorderedFilterChain, new OrderComparator());
     OrderComparator就是过滤链的排序比较器了,比较算法部分代码:
    public int compare(Object o1, Object o2) {
    		boolean p1 = (o1 instanceof PriorityOrdered);
    		boolean p2 = (o2 instanceof PriorityOrdered);
    		if (p1 && !p2) {
    			return -1;
    		}
    		else if (p2 && !p1) {
    			return 1;
    		}
    
    		// Direct evaluation instead of Integer.compareTo to avoid unnecessary object creation.
    		int i1 = getOrder(o1);
    		int i2 = getOrder(o2);
    		return (i1 < i2) ? -1 : (i1 > i2) ? 1 : 0;
    	}
     检查自定义过滤链当指定position属性时有可能做成的位置冲突
  • private void checkFilterChainOrder(List<OrderDecorator> filters, ParserContext pc, Object source) {
            logger.info("Checking sorted filter chain: " + filters);
    
            for(int i=0; i < filters.size(); i++) {
                OrderDecorator filter = filters.get(i);
    
                if (i > 0) {
                    OrderDecorator previous = filters.get(i-1);
                    if (filter.getOrder() == previous.getOrder()) {
                        pc.getReaderContext().error("Filter beans '" + filter.bean + "' and '" +
                                previous.bean + "' have the same 'order' value. When using custom filters, " +
                                        "please make sure the positions do not conflict with default filters. " +
                                        "Alternatively you can disable the default filters by removing the corresponding " +
                                        "child elements from <http> and avoiding the use of <http auto-config='true'>.", source);
                    }
                }
            }
        }
     
  • Spring Security用枚举类型org.springframework.security.config.http.SecurityFilters来维护filter的顺序,再用org.springframework.security.config.http.OrderDecorator来包装filter及filter的顺序,再由org.springframework.core.OrderComparator比较filter的先后顺序。
  • 要自定义Spring Security的过滤链就必须了解filter的先后顺序,否者Spring Security不会正常运作。
  • 在web.xml添加spring security过滤器代理
    <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>
     
  • 在web.xml添加session 事件发布
    <listener>
            <listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
        </listener>
     
  • spring security 配置文件如下:
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:security="http://www.springframework.org/schema/security"
           xmlns="http://www.springframework.org/schema/beans"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/security
           http://www.springframework.org/schema/security/spring-security.xsd">
        <bean id="springSecurityFilterChain" class="org.springframework.security.web.FilterChainProxy">
            <security:filter-chain-map request-matcher="ant">
                <security:filter-chain pattern="/**" filters="
                    securityContextPersistenceFilter,
                    currentSessionFilter,
                    asyncManagerIntegrationFilter,
                    logoutFilter,
                    usernamePasswordAuthenticationFilter,
                    basicAuthenticationFilter,
                    requestCacheAwareFilter,
                    contextHolderAwareRequestFilter,
                    rememberMeAuthenticationFilter,
                    anonymousAuthenticationFilter,
                    sessionManagementFilter,
                    exceptionTranslationFilter,
                    filterSecurityInterceptor
                "/>
            </security:filter-chain-map>
        </bean>
        <bean id="securityContextPersistenceFilter"
              class="org.springframework.security.web.context.SecurityContextPersistenceFilter">
            <constructor-arg ref="securityContextRepository"/>
            <property name="forceEagerSessionCreation" value="false"/>
        </bean>
        <bean id="securityContextRepository"
              class="org.springframework.security.web.context.HttpSessionSecurityContextRepository">
            <property name="allowSessionCreation" value="true"/>
        </bean>
        <bean id="usernamePasswordAuthenticationFilter"
              class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
            <property name="authenticationManager" ref="customAuthenticationManager"/>
            <property name="usernameParameter" value="username"/>
            <property name="passwordParameter" value="password"/>
            <property name="rememberMeServices" ref="enhancedPersistentTokenBasedRememberMeServices"/>
            <property name="sessionAuthenticationStrategy" ref="compositeSessionAuthenticationStrategy"/>
            <property name="authenticationSuccessHandler" ref="savedRequestAwareAuthenticationSuccessHandler" />
            <property name="authenticationFailureHandler" ref="simpleUrlAuthenticationFailureHandler" />
            <property name="requiresAuthenticationRequestMatcher" ref="filterProcessUrlRequestMatcher" />
            <property name="allowSessionCreation" value="true"/>
        </bean>
        <bean id="savedRequestAwareAuthenticationSuccessHandler" class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler" >
            <property name="requestCache" ref="httpSessionRequestCache" />
            <property name="defaultTargetUrl" value="/home.html" />
        </bean>
        <bean id="anonymousAuthenticationFilter"
              class="org.springframework.security.web.authentication.AnonymousAuthenticationFilter">
            <constructor-arg value="BF93JFJ091N00Q7HF"/>
        </bean>
        <bean id="filterSecurityInterceptor"
              class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
            <property name="authenticationManager" ref="customAuthenticationManager"/>
            <property name="accessDecisionManager" ref="affirmativeBased"/>
            <property name="securityMetadataSource">
                <security:filter-security-metadata-source use-expressions="true">
                    <security:intercept-url pattern="/css/*" access="permitAll"/>
                    <security:intercept-url pattern="/js/*" access="permitAll"/>
                    <security:intercept-url pattern="/fonts/*" access="permitAll"/>
                    <security:intercept-url pattern="/signup.html*" access="permitAll"/>
                    <security:intercept-url pattern="/login.html*" access="permitAll"/>
                    <security:intercept-url pattern="/category.html*" access="permitAll"/>
                    <security:intercept-url pattern="/category.html*" access="permitAll"/>
                    <security:intercept-url pattern="/*" access="hasRole('ROLE_USER')"/>
    
                </security:filter-security-metadata-source>
            </property>
        </bean>
        <bean id="affirmativeBased" class="org.springframework.security.access.vote.AffirmativeBased">
            <constructor-arg type="java.util.List">
                <list>
                    <ref bean="expressionVoter"/>
                    <ref bean="roleVoter"/>
                    <ref bean="authenticatedVoter"/>
                </list>
            </constructor-arg>
        </bean>
        <bean id="roleVoter" class="org.springframework.security.access.vote.RoleVoter"/>
        <bean id="authenticatedVoter" class="org.springframework.security.access.vote.AuthenticatedVoter"/>
        <bean id="daoAuthenticationProvider"
              class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
            <property name="userDetailsService" ref="userDao"/>
            <property name="passwordEncoder" ref="passwordEncoder"/>
        </bean>
        <bean id="anonymousAuthenticationProvider"
              class="org.springframework.security.authentication.AnonymousAuthenticationProvider">
            <constructor-arg type="java.lang.String" value="BF93JFJ091N00Q7HF"/>
        </bean>
        <bean id="customAuthenticationManager" class="org.springframework.security.authentication.ProviderManager">
            <constructor-arg type="java.util.List">
                <list>
                    <ref bean="daoAuthenticationProvider"/>
                    <ref bean="anonymousAuthenticationProvider"/>
                    <ref bean="rememberMeAuthenticationProvider"/>
                </list>
            </constructor-arg>
            <property name="authenticationEventPublisher" ref="defaultAuthenticationEventPublisher" />
        </bean>
        <bean id="logoutFilter" class="org.springframework.security.web.authentication.logout.LogoutFilter">
            <constructor-arg type="java.lang.String" value="/"/>
            <constructor-arg>
                <array>
                    <ref bean="logoutHandler"/>
                    <ref bean="enhancedPersistentTokenBasedRememberMeServices"/>
                </array>
            </constructor-arg>
            <property name="logoutRequestMatcher" ref="logoutFilterProcessUrlRequestMatcher" />
        </bean>
    
    
        <bean id="rememberMeAuthenticationFilter"
              class="org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter">
            <constructor-arg ref="customAuthenticationManager"/>
            <constructor-arg ref="enhancedPersistentTokenBasedRememberMeServices"/>
        </bean>
        <bean id="enhancedPersistentTokenBasedRememberMeServices"
              class="com.aasonwu.mycompany.EnhancedPersistentTokenBasedRememberMeServices">
            <constructor-arg type="java.lang.String"
                             value="BoSk70Yar38~veg91DoCKs=sLaIn!metE55bURgs71rug;ILEa=Ikon79sept+ree$Fuel99baKER;wOe43JackS=TinS79babA73tiLmibs10bIsE*"/>
            <constructor-arg type="org.springframework.security.core.userdetails.UserDetailsService"
                             ref="userDao"/>
            <constructor-arg
                    type="org.springframework.security.web.authentication.rememberme.PersistentTokenRepository"
                    ref="jdbcTokenRepository"/>
            <property name="cookieName" value="MYCOMPANY_REMEMBER_ME"/>
            <property name="parameter" value="remember_me"/>
        </bean>
    
        <bean id="jdbcTokenRepository"
              class="org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl">
            <property name="dataSource" ref="dataSource"/>
        </bean>
    
        <bean id="rememberMeAuthenticationProvider"
              class="org.springframework.security.authentication.RememberMeAuthenticationProvider">
            <constructor-arg
                    value="BoSk70Yar38~veg91DoCKs=sLaIn!metE55bURgs71rug;ILEa=Ikon79sept+ree$Fuel99baKER;wOe43JackS=TinS79babA73tiLmibs10bIsE*"/>
        </bean>
    
        <bean id="exceptionTranslationFilter" class="org.springframework.security.web.access.ExceptionTranslationFilter">
            <constructor-arg ref="loginUrlAuthenticationEntryPoint"/>
            <constructor-arg ref="httpSessionRequestCache"/>
            <property name="accessDeniedHandler" ref="accessDeniedHandler"/>
        </bean>
    
        <bean id="loginUrlAuthenticationEntryPoint"
              class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
            <constructor-arg value="/login.html"/>
        </bean>
    
        <bean id="accessDeniedHandler" class="org.springframework.security.web.access.AccessDeniedHandlerImpl">
            <property name="errorPage" value="/accessDenied.html"/>
        </bean>
    
        <bean id="expressionHandler"
              class="org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler"/>
    
        <bean id="expressionVoter" class="org.springframework.security.web.access.expression.WebExpressionVoter">
            <property name="expressionHandler" ref="expressionHandler"/>
        </bean>
        <!--session manager-->
        <bean id="currentSessionFilter" class="org.springframework.security.web.session.ConcurrentSessionFilter">
            <constructor-arg type="org.springframework.security.core.session.SessionRegistry" ref="sessionRegistry"/>
            <constructor-arg type="java.lang.String" value="/login.html"/>
            <property name="logoutHandlers" ref="logoutHandler"/>
        </bean>
        <bean id="logoutHandler"
              class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler">
            <property name="invalidateHttpSession" value="true"/>
            <property name="clearAuthentication" value="true"/>
        </bean>
        <bean id="sessionManagementFilter" class="org.springframework.security.web.session.SessionManagementFilter">
            <constructor-arg ref="securityContextRepository"/>
            <constructor-arg ref="compositeSessionAuthenticationStrategy"/>
            <property name="authenticationFailureHandler" ref="simpleUrlAuthenticationFailureHandler"/>
            <!--<property name="invalidSessionStrategy" ref="simpleRedirectInvalidSessionStrategy" />-->
        </bean>
        <bean id="contextHolderAwareRequestFilter"
              class="org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter">
            <property name="authenticationManager" ref="customAuthenticationManager"/>
        </bean>
    
        <bean id="sessionRegistry" class="org.springframework.security.core.session.SessionRegistryImpl"/>
        <bean id="passwordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>
    
        <bean id="sessionFixationProtectionStrategy"
              class="org.springframework.security.web.authentication.session.SessionFixationProtectionStrategy">
            <property name="migrateSessionAttributes" value="true"/>
        </bean>
    
        <bean id="compositeSessionAuthenticationStrategy"
              class="org.springframework.security.web.authentication.session.CompositeSessionAuthenticationStrategy">
            <constructor-arg>
                <list>
                    <ref bean="sessionControlAuthenticationStrategy"/>
                    <ref bean="sessionFixationProtectionStrategy"/>
                    <ref bean="registerSessionAuthenticationStrategy"/>
                </list>
            </constructor-arg>
        </bean>
        <bean id="sessionControlAuthenticationStrategy"
              class="org.springframework.security.web.authentication.session.ConcurrentSessionControlAuthenticationStrategy">
            <constructor-arg ref="sessionRegistry"/>
            <property name="maximumSessions" value="1"/>
            <!--<property name="exceptionIfMaximumExceeded" value="false" />-->
        </bean>
        <bean id="registerSessionAuthenticationStrategy"
              class="org.springframework.security.web.authentication.session.RegisterSessionAuthenticationStrategy">
            <constructor-arg ref="sessionRegistry"/>
        </bean>
        <bean id="simpleUrlAuthenticationFailureHandler"
              class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
            <constructor-arg value="/login.html"/>
            <property name="allowSessionCreation" value="true" />
        </bean>
        <bean id="simpleRedirectInvalidSessionStrategy"
              class="org.springframework.security.web.session.SimpleRedirectInvalidSessionStrategy">
            <constructor-arg value="/accessDenied.html"/>
        </bean>
        <bean id="asyncManagerIntegrationFilter"
              class="org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter"/>
        <bean id="basicAuthenticationFilter"
              class="org.springframework.security.web.authentication.www.BasicAuthenticationFilter">
            <constructor-arg ref="customAuthenticationManager"/>
            <constructor-arg ref="basicAuthenticationEntryPoint"/>
        </bean>
        <bean id="basicAuthenticationEntryPoint"
              class="org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint">
            <property name="realmName" value="Spring Security Application"/>
        </bean>
    
        <bean id="httpSessionRequestCache" class="org.springframework.security.web.savedrequest.HttpSessionRequestCache">
            <property name="createSessionAllowed" value="true"/>
        </bean>
        <bean id="requestCacheAwareFilter" class="org.springframework.security.web.savedrequest.RequestCacheAwareFilter">
            <constructor-arg ref="httpSessionRequestCache"/>
        </bean>
        <bean id="defaultAuthenticationEventPublisher" class="org.springframework.security.authentication.DefaultAuthenticationEventPublisher" />
    
        <bean id="filterProcessUrlRequestMatcher" class="org.springframework.security.web.authentication.logout.LogoutFilter$FilterProcessUrlRequestMatcher">
            <constructor-arg value="/login" />
        </bean>
    
        <bean id="logoutFilterProcessUrlRequestMatcher" class="org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter$FilterProcessUrlRequestMatcher">
            <constructor-arg value="/logout"/>
        </bean>
    
        <security:global-method-security pre-post-annotations="enabled" />
    </beans>
     
  • 这个配置接近使用命名空间配置上下文的环境,并实现了自定义的userDetailServics, remember me 功能。
1
0
分享到:
评论
1 楼 李嘉铭 2015-06-11  
请问你对security4.0还有研究吗?他里面已经把FilterProcessUrlRequestMatcher这个内部类去掉了好像。

相关推荐

    Spring Security 中文教程.pdf

    1.1. Spring Security是什么? 1.2. 历史 1.3. 发行版本号 1.4. 获得Spring Security 1.4.1. 项目模块 1.4.1.1. Core - spring-security-core.jar 1.4.1.2. Web - spring-security-web.jar 1.4.1.3. ...

    SpringSecurity 3.0.1.RELEASE.CHM

    1.1. Spring Security是什么? 1.2. 历史 1.3. 发行版本号 1.4. 获得Spring Security 1.4.1. 项目模块 1.4.1.1. Core - spring-security-core.jar 1.4.1.2. Web - spring-security-web.jar 1.4.1.3. Config -...

    Spring Security-3.0.1中文官方文档(翻译版)

    Spring Security-3.0.1 中文官方文档(翻译版) 这次发布的Spring Security-3.0.1 是一个bug fix 版,主要是对3.0 中存在的一些问题进 行修 正。文档中没有添加新功能的介绍,但是将之前拼写错误的一些类名进行...

    单点登录sso-shiro-cas-maven

    class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor"&gt; &lt;bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"&gt; ...

    Java资源包01

    GWT Advanced Table 是一个基于 GWT 框架的网页表格组件,可实现分页数据显示、数据排序和过滤等功能! Google Tag Library 该标记库和 Google 有关。使用该标记库,利用 Google 为你的网站提供网站查询,并且可以...

    java开源包1

    GWT Advanced Table 是一个基于 GWT 框架的网页表格组件,可实现分页数据显示、数据排序和过滤等功能! Google Tag Library 该标记库和 Google 有关。使用该标记库,利用 Google 为你的网站提供网站查询,并且可以...

    java开源包11

    GWT Advanced Table 是一个基于 GWT 框架的网页表格组件,可实现分页数据显示、数据排序和过滤等功能! Google Tag Library 该标记库和 Google 有关。使用该标记库,利用 Google 为你的网站提供网站查询,并且可以...

    java开源包2

    GWT Advanced Table 是一个基于 GWT 框架的网页表格组件,可实现分页数据显示、数据排序和过滤等功能! Google Tag Library 该标记库和 Google 有关。使用该标记库,利用 Google 为你的网站提供网站查询,并且可以...

    java开源包3

    GWT Advanced Table 是一个基于 GWT 框架的网页表格组件,可实现分页数据显示、数据排序和过滤等功能! Google Tag Library 该标记库和 Google 有关。使用该标记库,利用 Google 为你的网站提供网站查询,并且可以...

    java开源包6

    GWT Advanced Table 是一个基于 GWT 框架的网页表格组件,可实现分页数据显示、数据排序和过滤等功能! Google Tag Library 该标记库和 Google 有关。使用该标记库,利用 Google 为你的网站提供网站查询,并且可以...

    java开源包5

    GWT Advanced Table 是一个基于 GWT 框架的网页表格组件,可实现分页数据显示、数据排序和过滤等功能! Google Tag Library 该标记库和 Google 有关。使用该标记库,利用 Google 为你的网站提供网站查询,并且可以...

    java开源包10

    GWT Advanced Table 是一个基于 GWT 框架的网页表格组件,可实现分页数据显示、数据排序和过滤等功能! Google Tag Library 该标记库和 Google 有关。使用该标记库,利用 Google 为你的网站提供网站查询,并且可以...

    java开源包4

    GWT Advanced Table 是一个基于 GWT 框架的网页表格组件,可实现分页数据显示、数据排序和过滤等功能! Google Tag Library 该标记库和 Google 有关。使用该标记库,利用 Google 为你的网站提供网站查询,并且可以...

    java开源包8

    GWT Advanced Table 是一个基于 GWT 框架的网页表格组件,可实现分页数据显示、数据排序和过滤等功能! Google Tag Library 该标记库和 Google 有关。使用该标记库,利用 Google 为你的网站提供网站查询,并且可以...

    java开源包7

    GWT Advanced Table 是一个基于 GWT 框架的网页表格组件,可实现分页数据显示、数据排序和过滤等功能! Google Tag Library 该标记库和 Google 有关。使用该标记库,利用 Google 为你的网站提供网站查询,并且可以...

    java开源包9

    GWT Advanced Table 是一个基于 GWT 框架的网页表格组件,可实现分页数据显示、数据排序和过滤等功能! Google Tag Library 该标记库和 Google 有关。使用该标记库,利用 Google 为你的网站提供网站查询,并且可以...

    java开源包101

    GWT Advanced Table 是一个基于 GWT 框架的网页表格组件,可实现分页数据显示、数据排序和过滤等功能! Google Tag Library 该标记库和 Google 有关。使用该标记库,利用 Google 为你的网站提供网站查询,并且可以...

    JAVA上百实例源码以及开源项目

    Java生成自定义控件源代码 2个目标文件 Java实现HTTP连接与浏览,Java源码下载 1个目标文件 摘要:Java源码,网络相关,HTTP  Java实现HTTP连接与浏览,Java源码下载,输入html文件地址或网址,显示页面和HTML源文件...

    JAVA上百实例源码以及开源项目源代码

    Java生成自定义控件源代码 2个目标文件 Java实现HTTP连接与浏览,Java源码下载 1个目标文件 摘要:Java源码,网络相关,HTTP  Java实现HTTP连接与浏览,Java源码下载,输入html文件地址或网址,显示页面和HTML源文件...

Global site tag (gtag.js) - Google Analytics