超越
VMware 提供培训和认证,助你加速进步。
了解更多用户应参考包含最新信息的Spring Security 参考文档。
在我的上一篇文章中,我介绍了 Spring Security 的 Java 配置,并讨论了项目的一些细节。在本文中,我们将首先介绍一个非常简单的 Web 安全配置。然后,我们将通过一些定制配置来稍微丰富一下内容。
本节我们将介绍基于 Web 的安全性的最基本配置。它可以分为四个步骤:
@EnableWebSecurity
注解和 WebSecurityConfigurerAdapter
协同工作,提供基于 Web 的安全性。通过扩展 WebSecurityConfigurerAdapter
并只用几行代码,我们可以实现以下功能:
@Configuration
@EnableWebSecurity
public class HelloWebSecurityConfiguration
extends WebSecurityConfigurerAdapter {
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER");
}
}
供你参考,这类似于以下 XML 配置,但有一些例外:
<http use-expressions="true">
<intercept-url pattern="/**" access="authenticated"/>
<logout
logout-success-url="/login?logout"
logout-url="/logout"
/>
<form-login
authentication-failure-url="/login?error"
login-page="/login"
login-processing-url="/login"
password-parameter="password"
username-parameter="username"
/>
</http>
<authentication-manager>
<authentication-provider>
<user-service>
<user name="user"
password="password"
authorities="ROLE_USER"/>
</user-service>
</authentication-provider>
</authentication-manager>
下一步是确保根 ApplicationContext
包含我们刚刚指定的 HelloWebSecurityConfiguration。实现这一点有许多不同的方法,但如果你使用的是 Spring 的 AbstractAnnotationConfigDispatcherServletInitializer,它可能看起来像这样:
public class SpringWebMvcInitializer extends
AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] { HelloWebSecurityConfiguration.class };
}
...
}
换句话说,传统上 Spring Security 是使用 web.xml 中类似于以下的代码行初始化的:
<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<!-- Load all Spring XML configuration including our security.xml file -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/*.xml</param-value>
</context-param>
[callout title="WebApplicationInitializer 的顺序"]如果在调用 AbstractSecurityWebApplicationInitializer 后添加任何 Servlet Filter 映射,它们可能会意外地被添加到 springSecurityFilterChain 之前。除非应用程序包含不需要保护的 Filter 实例,否则 springSecurityFilterChain 应该在任何其他 Filter 映射之前。@Order 注解可以用来帮助确保任何 WebApplicationInitializer 都以确定的顺序加载。[/callout]
最后一步是我们需要映射 springSecurityFilterChain
。通过扩展 AbstractSecurityWebApplicationInitializer 并可选地覆盖方法来定制映射,我们可以轻松做到这一点。
下面最基本的示例接受默认映射,并添加具有以下特性的 springSecurityFilterChain:
ERROR
和 REQUEST
的分发类型springSecurityFilterChain
映射被插入到任何已经配置的 Servlet Filter 映射之前
public class SecurityWebApplicationInitializer
extends AbstractSecurityWebApplicationInitializer {
}
上面的代码等效于 web.xml 中的以下几行:
<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>
<dispatcher>ERROR</dispatcher>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
我们的HelloWebSecurityConfiguration 示例展示了 Spring Security Java 配置可以为我们提供一些非常好的默认设置。让我们来看看一些基本的定制。
@EnableWebSecurity
@Configuration
public class CustomWebSecurityConfigurerAdapter extends
WebSecurityConfigurerAdapter {
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) {
auth
.inMemoryAuthentication()
.withUser("user") // #1
.password("password")
.roles("USER")
.and()
.withUser("admin") // #2
.password("password")
.roles("ADMIN","USER");
}
@Override
public void configure(WebSecurity web) throws Exception {
web
.ignoring()
.antMatchers("/resources/**"); // #3
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeUrls()
.antMatchers("/signup","/about").permitAll() // #4
.antMatchers("/admin/**").hasRole("ADMIN") // #6
.anyRequest().authenticated() // 7
.and()
.formLogin() // #8
.loginUrl("/login") // #9
.permitAll(); // #5
}
}
假设我们调整 AbstractAnnotationConfigDispatcherServletInitializer 来加载我们的新配置,我们的 CustomWebSecurityConfigurerAdapter 将执行以下操作:
对于熟悉基于 XML 配置的人来说,上面的配置与以下 XML 配置非常相似:
<http security="none" pattern="/resources/**"/>
<http use-expressions="true">
<intercept-url pattern="/logout" access="permitAll"/>
<intercept-url pattern="/login" access="permitAll"/>
<intercept-url pattern="/signup" access="permitAll"/>
<intercept-url pattern="/about" access="permitAll"/>
<intercept-url pattern="/**" access="hasRole('ROLE_USER')"/>
<logout
logout-success-url="/login?logout"
logout-url="/logout"
/>
<form-login
authentication-failure-url="/login?error"
login-page="/login"
login-processing-url="/login"
password-parameter="password"
username-parameter="username"
/>
</http>
<authentication-manager>
<authentication-provider>
<user-service>
<user name="user"
password="password"
authorities="ROLE_USER"/>
<user name="admin"
password="password"
authorities="ROLE_USER,ROLE_ADMIN"/>
</user-service>
</authentication-provider>
</authentication-manager>
在看了我们这个稍微复杂一点的示例后,你可能会发现 XML 命名空间和 Java 配置之间有一些相似之处。以下是一些更有用的要点:
你也会注意到 XML 和 Java 配置之间有一些重要的区别。
示例兼容性 由于代码已在没有更改的情况下合并到 Spring Security 3.2 M2 中,因此示例将兼容独立模块或 spring-security-config-3.2.0.M2+
我们提供了一些示例,展示了如何使用 Spring Security Java 配置来保护你的 Web 应用程序,希望能引起你的兴趣。下面你可以找到一些包含更多示例的资源。
如果你在将 XML 命名空间转换为 Java 配置时遇到困难,可以参考测试。惯例是,给定 XML 元素的测试将以 "Namespace" 开头,包含 XML 元素名称,并以 "Tests" 结尾。例如,要了解 http 元素如何映射到 Java 配置,你可以参考 NamespaceHttpTests。另一个示例是,你可以在 NamespaceRememberMeTests 中了解 remember-me 命名空间如何映射到 Java 配置。
如果你遇到错误、有改进想法等,请随时提出!我们很想听取你的意见,以确保在代码正式发布前一切正常。尽早试用新功能是回馈社区的一种良好而简单的方式。这也确保了你想要的功能存在并按你期望的方式工作。
请将任何问题或功能请求记录在 Spring Security JIRA 的 "Java Config" 类别下。在提交 JIRA 后,我们鼓励(但不强制要求)你以拉取请求的形式提交你的更改。你可以在贡献者指南中阅读更多关于如何操作的信息。
如果你对如何做某事有疑问,请使用Spring Security 论坛或在Stack Overflow 上使用 spring-security 标签提问(我会密切关注)。如果你对这篇博客有任何具体的评论或问题,请随时留言。使用适当的工具将有助于使每个人都更容易。
你应该对如何使用 Spring Security 的 Java 配置实现基于 Web 的安全性有了相当好的了解。在下一篇文章中,我们将探讨如何使用 Java 配置设置基于方法的安全性。