- 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的顺序,再用rg.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 功能。
相关推荐
Spring Security通过一系列拦截器( Filters )来保护我们的应用程序。当用户尝试访问受保护的资源时,这些拦截器会检查用户是否已经通过了身份验证。如果没有,它会将用户重定向到登录页面。一旦用户成功登录,...
Spring Security还支持自定义过滤器和过滤链,以满足特定需求。例如,你可以添加自己的过滤器来实现自定义的认证或授权逻辑。 总的来说,Spring Security 3.x提供了一套全面的安全解决方案,包括身份验证、授权、...
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 -...
在这个例子中,我们看到`ContextLoaderListener`用于初始化Spring应用上下文,`DelegatingFilterProxy`作为Spring Security的过滤器链的代理。`springSecurityFilterChain`过滤器映射到所有的URL,这意味着Spring ...
接下来,定义一个名为 `springSecurityFilterChain` 的过滤器,使用 `DelegatingFilterProxy` 类来代理 Spring Security 的过滤链。最后,配置过滤器映射,将所有请求(`/*`)都通过此过滤器处理。`welcome-file-...
- **过滤器(Filters)**:Spring Security使用一系列过滤器来处理安全性相关的请求; - **认证管理器(Authentication Manager)**:负责验证用户的凭证; - **授权(Authorization)**:根据用户的角色或权限控制...
- **过滤器 (Filters)**:Spring Security 使用一系列过滤器来处理 HTTP 请求,执行认证和授权过程。 - **访问决策管理 (Access Decision Manager)**:负责确定用户是否有权限访问某个资源。 - **安全上下文 ...
Gateway可以结合Spring Security实现权限控制,也可以集成Spring Boot Actuator进行性能监控。 8. **过滤器链执行机制** 每个路由定义的过滤器会按照顺序执行,全局过滤器在路由过滤器之前运行,形成一个完整的...
我们需要创建一个自定义的过滤器,负责在登录请求到达后检查请求中的验证码是否正确。这个过滤器可以继承自 `GatewayFilter`,并在 `filter` 方法中实现验证码的校验逻辑: ```java @Component public class ...
总的来说,集成Spring Security 2.0(原Acegi 2.x)涉及到的主要步骤包括:配置Spring环境、声明Spring Security过滤器、在`applicationContext.xml`中引入安全命名空间并进行具体的安全配置。通过这种方式,我们...
同时,通过`shiroFilter`将Shiro的过滤器链绑定到Spring MVC。 5. **编写Controller**:在Controller中,可以通过`@ShiroRequiresPermissions`和`@ShiroRequiresRoles`注解进行权限控制,限制对特定方法的访问。 6...
5. ** Filters**:Spring Security通过一系列过滤器链来实现其功能,如`UsernamePasswordAuthenticationFilter`用于处理登录请求,`RememberMeAuthenticationFilter`处理记住我功能,`AnonymousAuthenticationFilter...
例如,你可能需要自定义认证方式,添加自定义过滤器,或者改变默认的安全策略。`applicationContext-security.xml` 是配置 Acegi 安全策略的主要入口,因此理解并熟练掌握这个文件对于维护和扩展安全系统至关重要。 ...
SpringBoot框架是Java生态系统中的一个核心组件,它...结合Spring Security、过滤器和拦截器,我们可以构建安全、可扩展的Web应用。在实际项目中,我们需要根据需求来灵活运用这些工具,以实现高效且健壮的解决方案。
- 自定义过滤器时,需要继承ZuulFilter类,实现filterType、filterOrder、shouldFilter方法,并在run方法中编写业务逻辑。 - 过滤器执行顺序由filterOrder决定,filterType定义了过滤器类型。 9. **监控与调试** ...
在实际项目中,可以创建自定义过滤器或利用现有的开源过滤器库,如Apache Shiro或Spring Security来实现这些功能。文件名"filters-main"可能是一个包含过滤器主类或者配置的文件,它会定义过滤器链以及各个过滤器的...
- Spring Security Filter Chain配置:将Shiro的过滤器与Spring的DispatcherServlet结合,定义安全过滤链。 - Session管理和缓存相关配置:可能涉及到如何存储和管理会话,以及缓存策略。 通过对"shirospring"源码...
Spring Security(以前称为 Acegi Security)是 Spring 生态系统中的安全模块,提供更复杂的安全需求。 3. **Shiro 和 Spring 集成的优势** - **代码简洁**:Shiro 的 API 直观易懂,与 Spring 结合使用,可以避免...
创建一个简单的 Spring Cloud Gateway 项目,定义路由规则,编写自定义过滤器,然后启动项目,通过发送请求测试路由和过滤器的正确性。 ### 8. 相关技术 - **Spring Cloud Core**: 提供 Spring Cloud 的基础工具和...
- **过滤器**:自定义过滤器实现请求的预处理和后处理,如身份验证、限流、熔断等。 - **动态路由**:支持动态更新路由配置,无需重启服务。 - **负载均衡**:内置Ribbon支持,可实现客户端负载均衡。 - **服务...