大多数 Spring Security 用户将在使用 HTTP 和 Servlet API 的应用程序中使用框架。在本部分中,我们将了解 Spring Security 如何为应用程序的 web 层提供身份验证和访问控制特性。我们将在命名空间的外观后面进行查看,并查看实际组装了哪些类和接口来提供 web 层安全性。在某些情况下,有必要使用传统的 bean 配置来提供对配置的完全控制,因此我们还将了解如何在没有命名空间的情况下直接配置这些类。
Spring Security 的 web 基础设施完全基于标准的 servlet 过滤器。它在内部不使用 servlet 或任何其它基于 servlet 的框架(如 Spring MVC),因此它没有与任何特定 web 技术的强链接。它处理 Spring Security 在内部维护一个过滤器链,其中每个过滤器具有特定的责任,并且根据需要哪些服务从配置中添加或删除过滤器。过滤器的排序很重要,因为它们之间存在依赖关系。如果你一直使用命名空间配置,那么过滤器将为你自动配置,并且你不必显式地定义任何 Spring bean,但是有时候你需要完全控制安全过滤器链,因为你使用的特性不是在命名空间中进行支持,或者使用自己自定义的类版本。
当使用 servlet 过滤器时,你显然需要在
当使用 <filter> <filter-name>myFilter</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> </filter> <filter-mapping> <filter-name>myFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
注意,过滤器实际上是一个
Spring Security 的 web 基础结构只应通过委派给 <bean id="filterChainProxy" class="org.springframework.security.web.FilterChainProxy"> <constructor-arg> <list> <sec:filter-chain pattern="/restful/**" filters=" securityContextPersistenceFilterWithASCFalse, basicAuthenticationFilter, exceptionTranslationFilter, filterSecurityInterceptor" /> <sec:filter-chain pattern="/**" filters=" securityContextPersistenceFilterWithASCTrue, formLoginFilter, exceptionTranslationFilter, filterSecurityInterceptor" /> </list> </constructor-arg> </bean>
命名空间元素
你可能已经注意到我们已经在过滤器链中声明了两个
请注意,
当我们研究如何使用命名空间配置设置 web 安全时,我们使用了名为 "springSecurityFilterChain" 的 在链中定义过滤器的顺序是非常重要的。不管你实际使用哪种过滤器,顺序应该如下:
Spring Security 有几个区域,你定义的模式针对传入的请求进行测试,以便决定如何处理请求。当
Servlet 规范为
如上所述,默认策略是使用 Ant 样式的路径进行匹配,这对于大多数用户来说可能是最佳选择。该策略在类
如果出于某种原因,需要更强大的匹配策略,可以使用正则表达式。策略实现是 在实践中,我们建议你在服务层使用方法安全性,以控制对应用程序的访问,并且不要完全依赖于在 web 应用程序级别定义的安全约束的使用。URL 会改变,很难考虑应用程序可能支持的所有可能的 URL 以及如何操作请求。你应该试着用一些简单易懂的 Ant 路径来限制自己。始终尝试使用默认拒绝的方法,在所有的通配符(或)定义了最后一个和拒绝访问。 在服务层定义的安全性更加健壮,并且更难绕过,因此你应该始终利用 Spring Security 的方法安全性选项。
默认情况下使用 <b:bean id="httpFirewall" class="org.springframework.security.web.firewall.StrictHttpFirewall" p:allowSemicolon="true"/> <http-firewall ref="httpFirewall"/>
同样的事情可以通过暴露一个 @Bean public StrictHttpFirewall httpFirewall() { StrictHttpFirewall firewall = new StrictHttpFirewall(); firewall.setAllowSemicolon(true); return firewall; }
<b:bean id="httpFirewall" class="org.springframework.security.web.firewall.StrictHttpFirewall" p:allowedHttpMethods="GET,HEAD"/> <http-firewall ref="httpFirewall"/>
同样的事情可以通过暴露一个 @Bean public StrictHttpFirewall httpFirewall() { StrictHttpFirewall firewall = new StrictHttpFirewall(); firewall.setAllowedHttpMethods(Arrays.asList("GET", "POST")); return firewall; }
如果你必须允许任何 HTTP 方法(不推荐),可以使用
如果你使用的是其它基于过滤器的框架,那么你需要确保 Spring Security 过滤器是第一个。这使得
正如我们在前面命名空间章节看到的,可以使用多个 <!-- Stateless RESTful service using Basic authentication --> <http pattern="/restful/**" create-session="stateless"> <intercept-url pattern='/**' access="hasRole('REMOTE')" /> <http-basic /> </http> <!-- Empty filter chain for the login page --> <http pattern="/login.htm*" security="none"/> <!-- Additional filter chain for normal users, matching all other requests --> <http> <intercept-url pattern='/**' access="hasRole('USER')" /> <form-login login-page='/login.htm' default-target-url="/home.htm"/> <logout /> </http>
[6] 请注意,你需要在应用程序程序上下文 XML 文件包含安全命名空间以使用这个语法。使用
[7] 可以使用
[8] 当浏览器不支持 cookie 并且
[9] 当请求离开
[10] 因此,例如,原始请求路径 |