`
aasonwu
  • 浏览: 35207 次
  • 性别: 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实现自定义登录认证.rar

    Spring Security通过一系列拦截器( Filters )来保护我们的应用程序。当用户尝试访问受保护的资源时,这些拦截器会检查用户是否已经通过了身份验证。如果没有,它会将用户重定向到登录页面。一旦用户成功登录,...

    spring_security3教程

    Spring Security还支持自定义过滤器和过滤链,以满足特定需求。例如,你可以添加自己的过滤器来实现自定义的认证或授权逻辑。 总的来说,Spring Security 3.x提供了一套全面的安全解决方案,包括身份验证、授权、...

    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_security3.2_详细配置_培训笔记

    在这个例子中,我们看到`ContextLoaderListener`用于初始化Spring应用上下文,`DelegatingFilterProxy`作为Spring Security的过滤器链的代理。`springSecurityFilterChain`过滤器映射到所有的URL,这意味着Spring ...

    spring-security3入门教程.doc

    接下来,定义一个名为 `springSecurityFilterChain` 的过滤器,使用 `DelegatingFilterProxy` 类来代理 Spring Security 的过滤链。最后,配置过滤器映射,将所有请求(`/*`)都通过此过滤器处理。`welcome-file-...

    SpringOne-Using Spring Security 2

    - **过滤器(Filters)**:Spring Security使用一系列过滤器来处理安全性相关的请求; - **认证管理器(Authentication Manager)**:负责验证用户的凭证; - **授权(Authorization)**:根据用户的角色或权限控制...

    Spring-security-test

    - **过滤器 (Filters)**:Spring Security 使用一系列过滤器来处理 HTTP 请求,执行认证和授权过程。 - **访问决策管理 (Access Decision Manager)**:负责确定用户是否有权限访问某个资源。 - **安全上下文 ...

    spring-cloud-gateway-example-master.zip

    Gateway可以结合Spring Security实现权限控制,也可以集成Spring Boot Actuator进行性能监控。 8. **过滤器链执行机制** 每个路由定义的过滤器会按照顺序执行,全局过滤器在路由过滤器之前运行,形成一个完整的...

    spring-gateway实现登录验证码校验的代码,百分百可用

    我们需要创建一个自定义的过滤器,负责在登录请求到达后检查请求中的验证码是否正确。这个过滤器可以继承自 `GatewayFilter`,并在 `filter` 方法中实现验证码的校验逻辑: ```java @Component public class ...

    如何在Spring中集成Acegi 2.x安全框架

    总的来说,集成Spring Security 2.0(原Acegi 2.x)涉及到的主要步骤包括:配置Spring环境、声明Spring Security过滤器、在`applicationContext.xml`中引入安全命名空间并进行具体的安全配置。通过这种方式,我们...

    spring shiro整合入门

    同时,通过`shiroFilter`将Shiro的过滤器链绑定到Spring MVC。 5. **编写Controller**:在Controller中,可以通过`@ShiroRequiresPermissions`和`@ShiroRequiresRoles`注解进行权限控制,限制对特定方法的访问。 6...

    javaspring

    5. ** Filters**:Spring Security通过一系列过滤器链来实现其功能,如`UsernamePasswordAuthenticationFilter`用于处理登录请求,`RememberMeAuthenticationFilter`处理记住我功能,`AnonymousAuthenticationFilter...

    Acegi 各过滤的解析(二)

    例如,你可能需要自定义认证方式,添加自定义过滤器,或者改变默认的安全策略。`applicationContext-security.xml` 是配置 Acegi 安全策略的主要入口,因此理解并熟练掌握这个文件对于维护和扩展安全系统至关重要。 ...

    SpringBoot框架

    SpringBoot框架是Java生态系统中的一个核心组件,它...结合Spring Security、过滤器和拦截器,我们可以构建安全、可扩展的Web应用。在实际项目中,我们需要根据需求来灵活运用这些工具,以实现高效且健壮的解决方案。

    spring cloud zuul 使用

    - 自定义过滤器时,需要继承ZuulFilter类,实现filterType、filterOrder、shouldFilter方法,并在run方法中编写业务逻辑。 - 过滤器执行顺序由filterOrder决定,filterType定义了过滤器类型。 9. **监控与调试** ...

    filters:一些适合您项目的过滤器

    在实际项目中,可以创建自定义过滤器或利用现有的开源过滤器库,如Apache Shiro或Spring Security来实现这些功能。文件名"filters-main"可能是一个包含过滤器主类或者配置的文件,它会定义过滤器链以及各个过滤器的...

    shirospring源码

    - Spring Security Filter Chain配置:将Shiro的过滤器与Spring的DispatcherServlet结合,定义安全过滤链。 - Session管理和缓存相关配置:可能涉及到如何存储和管理会话,以及缓存策略。 通过对"shirospring"源码...

    shiro+spring集成

    Spring Security(以前称为 Acegi Security)是 Spring 生态系统中的安全模块,提供更复杂的安全需求。 3. **Shiro 和 Spring 集成的优势** - **代码简洁**:Shiro 的 API 直观易懂,与 Spring 结合使用,可以避免...

    spring-cloud-gateway:基于Spring Framework 5.x和Spring Boot 2.x构建的网关,提供路由等

    创建一个简单的 Spring Cloud Gateway 项目,定义路由规则,编写自定义过滤器,然后启动项目,通过发送请求测试路由和过滤器的正确性。 ### 8. 相关技术 - **Spring Cloud Core**: 提供 Spring Cloud 的基础工具和...

    gateway学习相关资料.zip

    - **过滤器**:自定义过滤器实现请求的预处理和后处理,如身份验证、限流、熔断等。 - **动态路由**:支持动态更新路由配置,无需重启服务。 - **负载均衡**:内置Ribbon支持,可实现客户端负载均衡。 - **服务...

Global site tag (gtag.js) - Google Analytics