领先一步
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 配置设置基于方法的安全。