文章主要分三部分
1、Spring Security的架构及核心组件:(1)认证;(2)权限拦截;(3)数据库管理;(4)权限缓存;(5)自定义决策;
2、环境搭建与使用,使用当前热门的Spring Boot来搭建环境,结合项目中实际的例子来做几个Case;
3、Spring Security的优缺点总结,结合第二部分中几个Case的实现来总结Spring Security的优点和缺点。
1、Spring Security介绍
整体介绍,Spring Security为基于J2EE开发的企业应用软件提供了全面的安全服务,特别是使用Spring开发的企业软件项目,如果你熟悉Spring,尤其是Spring的依赖注入原理,这将帮助你更快掌握Spring Security,目前使用Spring Security有很多原因,通常因为在J2EE的Servlet规范和EJB规范中找不到典型应用场景的解决方案,提到这些规范,特别要指出的是它们不能在WAR或EAR级别进行移植,这样如果你需要更换服务器环境,就要在新的目标环境中进行大量的工作,对你的应用进行重新配置安全,使用Spring Security就解决了这些问题,也为你提供了很多很有用的可定制的安全特性。
Spring Security包含三个主要的组件:SecurityContext
、AuthenticationManager
、AccessDecisionManager
.
图1-1 Spring Security主要组件
1.1 认证
Spring Security提供了很多过滤器,它们拦截Servlet请求,并将这些请求转交给认证处理过滤器和访问决策过滤器进行处理,并强制安全性认证用户身份和用户权限以达到保护WEB资源的目的,Spring Security安全机制包括两个主要的操作,认证和验证,验证也可以称为权限控制,这是Spring Security两个主要的方向,认证是为用户建立一个他所声明的主体的过程,这个主体一般是指用户设备或可以在系统中执行行动的其他系统,验证指用户能否在应用中执行某个操作,在到达授权判断之前身份的主体已经由身份认证过程建立了。下面列出几种常用认证模式,这里不对它们作详细介绍,需要详细了解的老铁们可以自行查查对应的资料。
Basic
:HTTP1.0
提出,一种基于challenge/response的认证模式,针对特定的realm需要提供用户名和密码认证后才可访问,其中密码使用明文传输。缺点:①无状态导致每次通信都要带上认证信息,即使是已经认证过的资源;②传输安全性不足,认证信息用Base64
编码,基本就是明文传输,很容易对报文截取并盗用认证信息。Digest
:HTTP1.1
提出,它主要是为了解决Basic模式安全问题,用于替代原来的Basic认证模式,Digest认证也是采用challenge/response认证模式,基本的认证流程比较类似。Digest模式避免了密码在网络上明文传输,提高了安全性,但它仍然存在缺点,例如认证报文被攻击者拦截到攻击者可以获取到资源。X.509
:证书认证,X.509
是一种非常通用的证书格式,证书包含版本号、序列号(唯一)、签名、颁发者、有效期、主体、主体公钥。LDAP
:轻量级目录访问协议(Lightweight Directory Access Protocol)。Form
:基于表单的认证模式。
1.2 权限拦截
图1-2 用户请求
图1-3 过滤器
Spring Security提供了很多过滤器,其中SecurityContextPersistenceFilter
、UsernamePasswordAuthenticationFilter
、FilterSecurityInterceptor
分别对应SecurityContext
、AuthenticationManager
、AccessDecisionManager
的处理。
图1-4 Spring Security过滤链流程图
下面分别介绍各个过滤器的功能。
过滤器 | 描述 |
---|---|
WebAsyncManagerIntegrationFilter |
设置SecurityContext 到异步线程中,用于获取用户上下文信息 |
SecurityContextPersistenceFilter |
整个请求过程中SecurityContext 的创建和清理1.未登录, SecurityContext 为null,创建一个新的ThreadLocal 的SecurityContext 填充SecurityContextHolder .2.已登录,从 SecurityContextRepository 获取的SecurityContext 对象.两个请求完成后都清空 SecurityContextHolder ,并更新SecurityContextRepository |
HeaderWriterFilter |
添加头信息到响应对象 |
CsrfFilter |
防止csrf攻击(跨站请求伪造)的过滤器 |
LogoutFilter |
登出处理 |
UsernamePasswordAuthenticationFilter |
获取表单用户名和密码,处理基于表单的登录请求 |
DefaultLoginPageGeneratingFilter |
配置登录页面 |
BasicAuthenticationFilter |
检测和处理http basic认证,将结果放进SecurityContextHolder |
RequestCacheAwareFilter |
处理请求request的缓存 |
SecurityContextHolderAwareRequestFilter |
包装请求request,便于访问SecurityContextHolder |
AnonymousAuthenticationFilter |
匿名身份过滤器,不存在用户信息时调用该过滤器 |
SessionManagementFilter |
检测有用户登录认证时做相应的session管理 |
ExceptionTranslationFilter |
处理AccessDeniedException 访问异常和AuthenticationException 认证异常 |
FilterSecurityInterceptor |
检测用户是否具有访问资源路径的权限 |
1.3 数据库管理
图1-5 Spring Security核心处理流程
上图展示的Spring Security核心处理流程。当一个用户登录时,会先进行身份认证,如果身份认证未通过会要求用户重新认证,当用户身份证通过后就会调用角色管理器判断他是否可以访问,这里,如果要实现数据库管理用户及权限,就需要自定义用户登录功能,Spring Security已经提供好了一个接口UserDetailsService
。
package org.springframework.security.core.userdetails;
public interface UserDetailsService {
/**
* Locates the user based on the username. In the actual implementation, the search
* may possibly be case sensitive, or case insensitive depending on how the
* implementation instance is configured. In this case, the <code>UserDetails</code>
* object that comes back may have a username that is of a different case than what
* was actually requested..
*
* @param username the username identifying the user whose data is required.
*
* @return a fully populated user record (never <code>null</code>)
*
* @throws UsernameNotFoundException if the user could not be found or the user has no
* GrantedAuthority
*/
UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
}
UserDetailService
该接口只有一个方法,通过方法名可以看出方法是通过用户名来获取用户信息的,但返回结果是UserDetails
对象,UserDetails
也是一个接口,接口中任何一个方法返回false用户的凭证就会被视为无效。
package org.springframework.security.core.userdetails;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import java.io.Serializable;
import java.util.Collection;
/**
* Provides core user information.
*
* <p>
* Implementations are not used directly by Spring Security for security purposes. They
* simply store user information which is later encapsulated into {
@link Authentication}
* objects. This allows non-security related user information (such as email addresses,
* telephone numbers etc) to be stored in a convenient location.
* <p>
* Concrete implementations must take particular care to ensure the non-null contract
* detailed for each method is enforced. See
* {
@link org.springframework.security.core.userdetails.User} for a reference
* implementation (which you might like to extend or use in your code).
*
* @see UserDetailsSe