整体概述
运行时环境
Spring Security 3.0需要Java 5.0 Runtime Environment或更高版本。
核心组件
SecurityContextHolder,SecurityContext和Authentication Objects
最基本的对象是SecurityContextHolder。这是我们存储应用程序当前安全上下文的详细信息的地方,其中包括当前使用该应用程序的主体的详细信息。默认情况下,SecurityContextHolder使用ThreadLocal来存储这些详细信息,这意味着安全上下文始终可用于同一执行线程中的方法,即使安全上下文未作为参数显式传递那些方法。如果在处理当前委托人的请求之后小心地清除线程,以这种方式使用ThreadLocal是非常安全的。当然,Spring Security会自动为您解决这个问题,因此无需担心。
获取有关当前用户的信息
在SecurityContextHolder内,我们存储了当前与应用程序交互的主体的详细信息。Spring Security使用Authentication对象来表示此信息。您通常不需要自己创建Authentication对象,但用户查询Authentication对象是相当常见的。您可以使用以下代码块(从应用程序的任何位置)获取当前经过身份验证的用户的名称
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
if (principal instanceof UserDetails) {
String username = ((UserDetails)principal).getUsername();
} else {
String username = principal.toString();
}
UserDetailsService
用来查询
数据库,加载用户信息的接口 UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
需要注意
UserDetailsService经常有些混乱。它纯粹是用户数据的DAO,除了将数据提供给框架内的其他组件之外,不执行任何其他功能。特别是,它不会对用户进行身份验证,这是由AuthenticationManager完成的。在许多情况下,如果您需要自定义身份验证过程,直接实现AuthenticationProvider会更有意义。
GrantedAuthority
除了校长之外,Authentication提供的另一个重要方法是getAuthorities()。此方法提供GrantedAuthority个对象的数组。毫不奇怪,GrantedAuthority是授予校长的权力。这些权力通常是“角色”,例如ROLE_ADMINISTRATOR或ROLE_HR_SUPERVISOR。稍后将为web授权,方法授权和域对象授权配置这些角色。Spring Security的其他部分能够解释这些权威,并期望它们存在。GrantedAuthority对象通常由UserDetailsService加载。
小结
回顾一下,到目前为止我们看到的Spring Security的主要构建块是:
SecurityContextHolder,提供SecurityContext的访问权限。
SecurityContext,保存Authentication和可能的特定于请求的安全信息。
Authentication,以特定于Spring Security的方式代表校长。
GrantedAuthority,以反映授予主体的应用程序范围的权限。
UserDetails,提供从应用程序的DAO或其他安全数据源构建Authentication对象所需的信息。
UserDetailsService,在基于String的用户名(或证书ID等)中传递时创建UserDetails。
认证Authentication
在Spring Security内认证的流程。
- 获取用户名和密码并将其合并到UsernamePasswordAuthenticationToken的实例中(我们之前看到的Authentication接口的实例)。
- 令牌被传递给AuthenticationManager的实例以进行验证。
- AuthenticationManager在成功验证后返回完全填充的Authentication实例。
- 通过调用SecurityContextHolder.getContext().setAuthentication(…)建立安全上下文,传入返回的身份验证对象。
例子:
结果
Please enter your username:
hi
Please enter your password:
hi1
Authentication failed: Bad Credentials
Please enter your username:
hi
Please enter your password:
hi
Successfully authenticated. Security context contains: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@441d0230: Principal: hi; Credentials: [PROTECTED]; Authenticated: true; Details: null; Granted Authorities: ROLE_USER
web应用中的验证 Authentication in a Web Application
考虑典型的web应用程序的身份验证过程:
- 您访问主页,然后单击链接。
- 请求转到服务器,服务器确定您已请求受保护的资源。
- 由于您目前尚未通过身份验证,因此服务器会发回一个响应,指示您必须进行身份验证。响应将是HTTP响应代码,或重定向到特定的web页面。
- 根据身份验证机制,您的浏览器将重定向到特定的web页面,以便您可以填写表单,或者浏览器将以某种方式检索您的身份(通过BASIC身份验证对话框,cookie,X. 509证书等)。
- 浏览器将向服务器发回响应。这将是包含您填写的表单内容的HTTP POST,或者包含您的身份验证详细信息的HTTP标头。
- 接下来,服务器将决定所呈现的凭证是否有效。如果它们有效,则下一步将会发生。如果它们无效,通常会要求您的浏览器再次尝试(因此您将返回上面的第二步)。
- 将重试您进行身份验证过程的原始请求。希望您已通过足够授权的权限进行身份验证以访问受保护资源。如果您有足够的访问权限,请求将成功。否则,您将收到HTTP错误代码403,这意味着“禁止”。
ExceptionTranslationFilter
ExceptionTranslationFilter是一个Spring Security过滤器,负责检测抛出的任何Spring Security异常。AbstractSecurityInterceptor通常会抛出此类异常,这是授权服务的主要提供者。
AuthenticationEntryPoint
AuthenticationEntryPoint负责上面列表中的第三步。可以想象,每个web应用程序都有一个默认的身份验证策略(好吧,这可以像Spring Security中的几乎所有其他配置一样配置,但现在让我们保持简单)。每个主要身份验证系统都有自己的AuthenticationEntryPoint实现,通常执行步骤3中描述的操作之一。
在请求之间SecurityContext
在Spring Security中,在请求之间存储SecurityContext的责任落在SecurityContextPersistenceFilter上,默认情况下,该上下文将上下文存储为HTTP请求之间的HttpSession属性。
许多其他类型的应用程序(例如,无状态RESTful web服务)不使用HTTP会话,并将在每个请求上重新进行身份验证。但是,链中包含SecurityContextPersistenceFilter以确保在每次请求后清除SecurityContextHolder仍然很重要。
授权/访问控制 Access-Control (Authorization) in Spring Security
负责在Spring Security中做出访问控制决策的主界面是AccessDecisionManager。它有一个decide方法,它接受一个代表请求访问的主体的Authentication对象,一个“安全对象”(见下文)和一个适用于该对象的安全元数据属性列表(例如角色列表)这是获得访问所必需的。
aop
可以选择使用AspectJ或Spring AOP执行方法授权,也可以选择使用过滤器执行web请求授权。您可以将这些方法中的零个,一个,两个或三个一起使用。主流使用模式是执行一些web请求授权,以及服务层上的一些Spring AOP方法调用授权。
AbstractSecurityInterceptor
AbstractSecurityInterceptor为处理安全对象请求提供了一致的工作流程,通常:
- 查找与当前请求关联的“配置属性”
- 将安全对象,当前Authentication和配置属性提交到AccessDecisionManager以进行授权决策
- (可选)更改发生调用的Authentication
- 允许安全对象调用继续(假设已授予访问权限)
- 调用返回后,调用AfterInvocationManager(如果已配置)。如果调用引发异常,则不会调用AfterInvocationManager。