核心组件
1)SecurityContextHolder
spring security最基本的类SecurityContextHolder
这里存储应用程序当前安全上下文的详细信息,其中包括当前使用的主体的详细信息,它使用ThreadLocal来存储这些信息,这意味着安全上下文对于整个线程的所有方法来讲都可用的,但是这不是对所有的应用来讲都是适用的,因为有些应用会要求所有的线程使用同一个上下文对象,这时我们将使用SecurityContextHolder.MODE_GLOBAL
来应对
2)获取当前用户的信息
在SecuritycontextHolder
中,我们存储当前与应用程序交互的主体的详细信息。Spring Security使用身份验证对象表示此信息。您通常不需要自己创建身份验证对象,但是用户查询身份验证对象是相当常见的。例如,您可以从应用程序中的任何位置使用以下代码块来获取当前经过身份验证的用户的名称
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
if (principal instanceof UserDetails) {
String username = ((UserDetails)principal).getUsername();
} else {
String username = principal.toString();
}
调用getContext()返回的对象是SecurityContext接口的一个实例。这是保存在线程本地存储中的对象。正如我们将在下面看到的,Spring Security中的大多数身份验证机制都返回一个UserDetails实例作为主体
3)UserDetailsService
对象
从上面的代码片段中需要注意的另一项是,您可以从Authentication
对象中获取主体。主体只是一个对象。大多数情况下,这可以转换为UserDetails
对象。UserDetails
是Spring Security中的一个核心接口。它表示主体,但是是以可扩展的和特定于应用程序的方式。将UserDetails
视为您自己的用户数据库和securitycontextholder
中Spring Security需要的适配器。作为来自您自己的用户数据库的内容的表示,您经常会将UserDetails转换为你的应用提供的原始对象,所以你可以调用特殊的业务方法,如getEmail(),getEmployeeNumber()
等等。
至此,你可能会像什么时候应该提供UserDetail对象呢?我怎么提供这个 对象呢?而这个是声明性的我不需要编写任何代码又是怎么回事呢?简单讲有一个叫UserDetailsService
的特殊接口,这个接口上唯一的方法接受一个基于字符串的username参数,并返回一个UserDetails:
UserDetails loadUserByUsername(String username) throws UsernameNotFoundException
这是在Spring Security中为用户加载信息的最常见方法,在需要用户信息时,您将看到它在整个框架中使用。
在成功进行身份验证时,UserDetails
用于构建存储在securitycontextholder
中的身份验证对象(下面将对此进行详细介绍)。好消息是我们提供了许多UserDetailsService
实现,包括一个使用内存映射(InMemoryDaoImpl)的实现和另一个使用JDBC (JdbcDaoImpl)的实现。但是,大多数用户倾向于编写自己的实现,他们的实现通常只是位于代表他们的雇员、客户或应用程序的其他用户的现有数据访问对象(DAO)之上。记住,无论UserDetailsService
返回什么,都可以使用上面的代码片段从SecurityContextHolder
获得。
提示:关于UserDetailsService经常会有一些混淆。它纯粹是一个用于用户数据的DAO,除了向框架内的其他组件提供数据之外,不执行任何其他功能。特别是,它不验证用户,这是由AuthenticationManager完成的。在许多情况下,如果需要自定义身份验证过程,则直接实现AuthenticationProvider更有意义
4)GrantedAuthority(授权)
除了主体之外,身份验证提供的另一个重要方法是getauthority()
。该方法提供了一个GrantedAuthority
对象数组。授予的权限是授予主体的权限,这并不奇怪。这些权限通常是“角色”,例如ROLE_ADMINISTRATOR
或ROLE_HR_SUPERVISOR
。稍后将为web授权、方法授权和域对象授权配置这些角色。Spring Security
的其他部分能够解释这些权限,并希望它们能够出现。GrantedAuthority
对象通常由UserDetailsService
加载
通常授予的权限对象是应用程序范围的权限。它们并不特定于给定的域对象。因此,您不太可能获得授权来表示Employee
对象的权限,因为如果有数千个这样的权限,您将很快耗尽内存(或者,至少会导致应用程序花很长时间来验证用户)。当然,Spring Security
是专门为处理这种常见需求而设计的,但是您可以为此使用项目的域对象安全功能
总结:
简单回顾一下,到目前为止我们所看到的Spring安全的主要构建块是:
1)提供对SecurityContext的访问。
2)SecurityContext,以保存身份验证和可能是特定于请求的安全信息。
3)身份验证,以特定于Spring安全的方式表示主体。
4)授予的权限,以反映授予主体的应用程序范围的权限。
5) UserDetails,以提供从应用程序的dao或其他安全数据源构建身份验证对象所需的信息。
6) UserDetailsService,用于在传入基于字符串的用户名(或证书ID或类似的名称)时创建用户详细信息
现在您已经了解了这些重复使用的组件,接下来让我们进一步了解身份验证的过程