简介:
Web 应用的安全性包括用户认证(Authentication)和用户授权(Authorization)两个部分。Spring Security是一个基于Spring AOP和Servlet过滤器的安全框架。
一、认证(Authentication):
Spring Security 目前支持所有这些技术集成的身份验证:
-
HTTP BASIC 认证头 (基于 IETF RFC-based 标准)
-
HTTP Digest 认证头 ( IETF RFC-based 标准)
-
HTTP X.509 客户端证书交换 ( IETF RFC-based 标准)
-
LDAP (一个非常常见的方法来跨平台认证需要, 尤其是在大型环境)
-
Form-based authentication (用于简单的用户界面)
-
OpenID 认证
-
Authentication based on pre-established request headers (such as Computer Associates Siteminder) 根据预先建立的请求有进行验证
-
JA-SIG Central Authentication Service (CAS,一个开源的SSO系统 )
-
Transparent authentication context propagation for Remote Method Invocation (RMI) and HttpInvoker (Spring远程协议)
-
Automatic "remember-me" authentication (你可以勾选一个框以避免预定的时间段再认证)
-
Anonymous authentication (让每一个未经验证的访问自动假设为一个特定的安全标识)
-
Run-as authentication (在一个访问应该使用不同的安全标识时非常有用)
-
Java Authentication and Authorization Service (JAAS)
-
JEE container autentication (所以如果愿你以可以任然使用容器管理的认证)
-
Kerberos
-
Java Open Source Single Sign On (JOSSO) *
-
OpenNMS Network Management Platform *
-
AppFuse *
-
AndroMDA *
-
Mule ESB *
-
Direct Web Request (DWR) *
-
Grails *
-
Tapestry *
-
JTrac *
-
Jasypt *
-
Roller *
-
Elastic Path *
-
Atlassian Crowd *
-
Your own authentication systems (see below)
(*)表示由第三方提供
二、用户授权(Authorization):
Java 配置:
一、基于表单登录页面:
1.默认:
如果Spring Security的配置没有设定一个登录页面的URL,Spring Security自动生成一个,这个功能被启用,使用默认URL处理登录的提交内容,登录后跳转的URL等等。
2. 自定义:
通过以下配置可提供自定义的登录页面。
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin() 1.基于表单登录
.loginPage("/login") 2.指定登录页的路径
.permitAll(); 3.必须允许所有用户访问我们的登录页
}
二、验证请求
通过给http.authorizeRequests()
添加多个子节点来指定多个定制需求到我们的URL,指定请求 验证匹配规则。
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests() 1.多个子节点,每个macher按照他们的声明顺序执行。
.antMatchers("/resources/**", "/signup", "/about").permitAll()
.antMatchers("/admin/**").hasRole("ADMIN")
.antMatchers("/db/**").access("hasRole('ADMIN') and hasRole('DBA')")
.anyRequest().authenticated() 2. 尚未匹配的任何URL要求用户进行身份验证
.and()
// ...
.formLogin();
}
三、处理登出
默认是访问URL`/logout`将注销登陆的用户,并且完成以下注销功能 。
-
使HTTP Session 无效
-
清楚所有已经配置的 RememberMe 认证
-
清除
SecurityContextHolder
-
跳转到
/login?logout
rotected void configure(HttpSecurity http) throws Exception {
http
.logout()
.logoutUrl("/my/logout") 1.触发注销操作的URL (默认是/logout).CSRF内启用(默认是启用的)请求的方式被限定为POST
.logoutSuccessUrl("/my/index") 2.注销之后跳转的URL。默认是/login?logout
.logoutSuccessHandler(logoutSuccessHandler) 3.定制的 LogoutSuccessHandler。如果指定了这个选项logoutSuccessUrl()的设置会被忽略.
.invalidateHttpSession(true)
.addLogoutHandler(logoutHandler) 4. 添加一个LogoutHandler
.deleteCookies(cookieNamesToClear)
.and()
...
}
1. LogoutHandler:
用来执行必要的清理(如:deleteCookies
),提供以下常用的LogoutHandler处理。
2.LogoutSuccessHandler:
用来进行重定向或者转发相应的目的地。提供的一些实现:
-
HttpStatusReturningLogoutSuccessHandler
处理过程:
public class LogoutFilter extends GenericFilterBean {
private final LogoutHandler handler;
private final LogoutSuccessHandler logoutSuccessHandler;
/**
* LogoutSuccessHandler:determine the target destination after logging out.
* The list of LogoutHandler: perform the actual logout functionality (such as clearing the security
* context, invalidating the session, etc.).
*/
public LogoutFilter(LogoutSuccessHandler logoutSuccessHandler,
LogoutHandler... handlers) {
this.handler = new CompositeLogoutHandler(handlers);
Assert.notNull(logoutSuccessHandler, "logoutSuccessHandler cannot be null");
this.logoutSuccessHandler = logoutSuccessHandler;
setFilterProcessesUrl("/logout");
}
// ~ Methods
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
if (requiresLogout(request, response)) {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
//LogoutFilter在成功注销后调用
this.handler.logout(request, response, auth);
logoutSuccessHandler.onLogoutSuccess(request, response, auth);
return;
}
chain.doFilter(request, response);
}
四、验证:
前面列出详尽的验证方式(HTTP BASIC、LDAP等),那如何指定使用哪种验证方式。还有从哪里加载用户验证信息(内存、JBDC、LDAP等)
http.authorizeRequests()
.antMatchers("/**")
.hasRole("USER")
.and()
.openidLogin() //指定OpenId验证方式
.loginPage("/login")
.permitAll()
..............
.httpBasic() //指定Http Basic验证方式
..............
.oauth2Login() //Oauth2.0 验证方式
1.指定验证方式
1.1基于表单的验证(Http Basic 验证):
默认情况下,spring security提供的是基于表单的验证(Http Basic 验证)。
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin() 1.基于表单登录
.and()
.httpBasic();2.指定使用HTTP基本身份验证
}
2. 用户身份加载方式(来源):
2.1.内存中的身份信息:
用户身份信息配置到内存验证中inMemoryAuthentication()
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER").and()
.withUser("admin").password("password").roles("USER", "ADMIN");
}
2.1 JDBC
用户的身份信息从JDBC数据库加载。
@Autowired
private DataSource dataSource;
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.jdbcAuthentication()
.dataSource(dataSource)
.withDefaultSchema()
.withUser("user").password("password").roles("USER").and()
.withUser("admin").password("password").roles("USER", "ADMIN");
}
3. LDAP
支持LDAP的身份验证
@Autowired
private DataSource dataSource;
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.ldapAuthentication()
.userDnPatterns("uid={0},ou=people")
.groupSearchBase("ou=groups");
}