- 浏览: 292897 次
- 性别:
- 来自: 唐山
最新评论
-
小灯笼:
JBPM5.4实战流程引擎开发网盘地址:https://pan ...
跟我学工作流——jBPM4视频教程(免费) -
Kai_Ge:
学会做人 写道临远大哥,谢谢你的贡献大名鼎鼎的临远!!膜拜中。 ...
Spring Security-3.0.1中文官方文档(翻译版) -
漂泊一剑客:
博主,你自己电脑上有下载,这些信息吗,能否分享一下给我
跟我学工作流——jBPM4视频教程(免费) -
Rookie_Li:
您好,您的教程很有用,请问例子的源码在哪下载?
spring security权限管理手册升级至spring security-3.1.3 -
nullFFF:
马教授 写道现在还用4有点过时了,最新的都已经是5.4了,目前 ...
跟我学工作流——jBPM4视频教程(免费)
技术概述
5.1. 运行环境
Spring Security可以运行在标准的Java 1.4运行环境下。 它也支持Java 5.0,不过这部分代码单独打包起来,放到发布的,文件名是"tiger"前缀的JAR文件里。 因为Spring Security的目标是自己容器内管理,所以不需要为你的Java运行环境进行什么特别的配置。 特别是,不需要特别配置一个Java Authentication and Authorization Service (JAAS)政策文件,也不需要把Spring Security放到server的classLoader下。
上面这些设计,确保了发布时的最大轻便性,你可以简单把你的目标文件(JAR或WAR或EAR)从一个系统复制到另一个系统,它会立即正常工作。
5.2. 共享组件
让我们展示一些Spring Security中很重要的共享组件。 被成为"shared"的组件,是指它在框架中占有很重要的位置,框架离开它们就没法运行。 这些java类表达了维持系统的构建代码块,所以理解他们的位置是非常重要的,即使你不需要直接跟他们打交道。
5.2.1. SecurityContextHolder, SecurityContext 和 Authentication对象
最基础的对象就是SecurityContextHolder。 我们把当前应用程序的当前安全环境的细节存储到它里边了。 默认情况下,SecurityContextHolder使用ThreadLocal存储这些信息,这意味着,安全环境在同一个线程执行的方法一直是有效的,即使这个安全环境没有作为一个方法参数传递到那些方法里。 这种情况下使用ThreadLocal是非常安全的,只要记得在处理完当前主体的请求以后,把这个线程清除就行了。 当然,Spring Security自动帮你管理这一切了,你就不用担心什么了。
有些程序并不适合使用ThreadLocal,因为它们处理线程的特殊方法。 比如,swing客户端也许希望JVM里的usoyou线程都使用同一个安全环境。 为了这种情况,我们而已使用SecurityContextHolder.MODE_GLOBAL。 其他程序可能想让一个线程创建的线程也使用相同的安全主体。 这时可以使用SecurityContextHolder.MODE_INHERITABLETHREADLOCAL。 想要修改默认的SecurityContextHolder.MODE_THREADLOCAL模式,可以使用两种方法。 第一个是设置系统属性。 另一个是调用SecurityContextHolder的静态方法。 大多数程序不需要修改默认值,但是如果你需要做修改,先看一下SecurityContextHolder的JavaDoc中的详细信息。
我们把安全主体和系统交互的信息都保存在SecurityContextHolder中了。 Spring Security使用一个Authentication对应来表现这些信息。 虽然你通常不需要自己创建一个Authentication对象,很常见的,用户查询Authentication对象。 你可以使用下面的代码-在你程序中的任何位置-来做这件事:
Object obj = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
if (obj instanceof UserDetails) {
String username = ((UserDetails)obj).getUsername();
} else {
String username = obj.toString();
}
上面的代码介绍了一定数量的,有趣的,几个关键对象之间的相互关系。 首先,你会注意到SecurityContextHolder 和 Authentication之间的中间对象。 这个SecurityContextHolder.getContext()方法会直接返回SecurityContext。
5.2.2. UserDetailsService
从上面的代码片段中还可以看出另一件事,就是你可以从Authentication对象中获得安全主体。 这个安全主体就是一个对象。 大多数情况下,可以强制转换成UserDetails对象。 UserDetails是一个Spring Security的核心接口。 它代表一个主体,是扩展的,而且是为特定程序服务的。 想一下UserDetails章节,在你自己的用户数据库和如何把Spring Security需要的数据放到SecurityContextHolder里。 为了让你自己的用户数据库起作用,我们常常把UserDetails转换成你系统提供的类,这样你就可以直接调用业务相关的方法了(比如getEmail(), getEmployeeNumber()等等)。
现在,你可能想知道,我应该什么时候提供这个UserDetails对象呢? 我怎么做呢? 我想你说这个东西是声明式的,我不需要写任何代码,怎么办? 简单的回答是,这里有一个特殊的接口,叫UserDetailsService。 这个接口里的唯一一个方法,接收String类型的用户名参数,返回UserDetails。 大多数验证提供器使用Spring Security代理UserDetailsService,作为验证过程的一部分。 这个UserDetailsService用来建立Authentication对象,保存在SecurityContextHolder里。 好消息是我们提供了好几个UserDetailsService实现,其中一个使用内存里的map,另一个使用JDBC。 虽然,大多数用户倾向于写自己的,使用这些实现常常放到已有的数据访问对象(DAO)上,表示它们的雇员,客户或其他企业应用中的用户。 记住这个优势,无论你用什么UserDetailsService返回的数据都可以通过SecurityContextHolder获得,就像上面的代码片段讲的一样。
5.2.3. GrantedAuthority
除了主体,另一个Authentication提供的重要方法是getAuthorities()。 这个方法提供了GrantedAuthority对象数组。 毫无疑问,GrantedAuthority是赋予到主体的权限。 这些权限通常使用角色表示,比如ROLE_ADMINISTRATOR 或 ROLE_HR_SUPERVISOR。 这些角色会在后面,对web验证,方法验证和领域对象验证进行配置。 Spring Security的其他部分用来拦截这些权限,期望他们被表现出现。 GrantedAuthority对象通常使用UserDetailsService读取的。
通常情况下,GrantedAuthority对象是应用程序范围下的授权。 它们不会特意分配给一个特定的领域对象。 因此,你不能设置一个GrantedAuthority,让它有权限展示编号54的Employee对象,因为如果有成千上网的这种授权,你会很快用光内存(或者,至少,导致程序花费大量时间去验证一个用户)。 当然,Spring Security被明确设计成处理常见的需求,但是你最好别因为这个目的使用项目领域模型安全功能。
最后,但不是最不重要的,优势你需要在HTTP请求之间共享SecurityContext. 其他时候,主体会在每个请求里重新验证,虽然大多数情况下它可以存储。 HttpSessionContextIntegrationFilter就是实现在HTTP请求之间存储SecurityContext的。 就像它的类名一样,HttpSession被用来保存这些信息。 你不应该因为安全的问题,直接与HttpSession打交道。 根本不存在这样做的理由-一直使用SecurityContextHolder作替代方式。
5.2.4. 小结
简单回顾一下,Spring Security主要是由一下几部分组成的:
*
SecurityContextHolder,提供几种访问SecurityContext的方式。
*
SecurityContext,保存Authentication信息,和请求对应的安全信息。
*
HttpSessionContextIntegrationFilter,为了在不同请求使用,把SecurityContext保存到 HttpSession里。
*
Authentication,展示Spring Security特定的主体。
*
GrantedAuthority,反应,在应用程序范围你,赋予主体的权限。
*
UserDetails,通过你的应用DAO,提供必要的信息,构建Authentication对象。
*
UserDetailsService,创建一个 UserDetails,传递一个 String类型的用户名(或者证书ID或其他)。
现在,你应该对这种重复使用的组件有一些了解了。 让我们贴近看一下验证的过程。
5.3. 验证
就像这篇指南开头提到的那样,Spring Security可在很多不同的验证环境下使用。 虽然我们推荐人们使用Spring Security,不与已存在的容器管理认证系统整合,但它也是支持的-使用你自己的属性验证系统进行整合。 让我们先看看Spring Security完全依靠自己,管理web安全,这里会演示最复杂和最常见的情况。
讨论一个典型的web应用验证过程:
1.
你访问首页,点击一个链接。
2.
向服务器发送一个请求,服务器判断你是否在访问一个受保护的资源。
3.
如果你还没有进行过认证,服务器发回一个响应,提示你必须进行认证。 响应可能是HTTP响应代码,或者是重新定向到一个特定的web页面。
4.
依据验证机制,你的浏览器将重定向到特定的web页面,这样你可以添加表单, 或者浏览器使用其他方式校验你的身份(比如,一个基本校验对话框,cookie,或者X509证书,或者其他)。
5.
浏览器会发回一个响应给服务器。 这将是HTTP POST包含你填写的表单内容,或者是HTTP头部,包含你的验证信息。
6.
下一步,服务器会判断当前的证书是否是有效的, 如果他们是有效的,下一步会执行。 如果他们是非法的,通常你的浏览器会再尝试一次(所以你返回的步骤二)。
7.
你发送的原始请求,会导致重新尝试验证过程。 有希望的是,你会通过验证,得到猪狗的授权,访问被保护的资源。 如果你有足够的权限,请求会成功。否则,你会收到一个HTTP错误代码403,意思是访问被拒绝。
Spring Security使用鲜明的类负责上面提到的每个步骤。 主要的部分是(为了使用他们)是ExceptionTranslationFilter, 一个AuthenticationEntryPoint, 一个验证机制,一个AuthenticationProvider。
5.3.1. ExceptionTranslationFilter
ExceptionTranslationFilter是一个Spring Security过滤器,用来检测是否抛出了Spring Security异常。 这些异常会被AbstractSecurityInterceptor抛出,它主要用来提供验证服务。 我们会在下一节讨论AbstractSecurityInterceptor,但是现在,我们只需要知道,它是用来生成Java异常,和知道跟HTTP没啥关系,或者如何验证一个主体。 而ExceptionTranslationFilter提供这些服务,使用特点那个的响应,返回错误代码403(如果主题被验证了,但是权限不足-在上边的步骤七),或者启动一个AuthenticationEntryPoint(如果主体没有认证,然后我们需要进入步骤三)。
5.3.2. AuthenticationEntryPoint
AuthenticationEntryPoint对应中上面列表中的步骤三。 如你所想的,每个web应用程序都有默认的验证策略(好的,这可以在Spring Security里配置一切,但是让我们现在保持简单)。 每个主要验证系统会有它自己的AuthenticationEntryPoint实现, 会执行动作,如同步骤三里的描述一样。
在你的浏览器决定提交你的认证证书之后(使用HTTP表单发送或者是HTTP头),服务器部分需要有一些东西来“收集”这些验证信息。 现在我们到了上述的第六步。 在Spring Security里,我们需要一个特定的名字,来描述从用户代码(通常是浏览器)收集验证信息的功能,这个名字就是“验证机制”。 在从用户代码哪里收集了验证细节之后,一个"Authentication 请求"对象会被AuthenticationProvider建立。
5.3.3. AuthenticationProvider
Spring Security认证过程的最后一个角色是AuthenticationProvider。 非常简单,这是跟获得Authentication请求对象相关的,决定它是否是有效的。 这个供应器或者抛出一个异常,或者返回一个完整的Authentication对象。 还记得我们的好朋友UserDetails和UserDetailsService吗? 如果不记得,回头看看前面的章节,刷新你的记忆。 大多数AuthenticationProvider都会要求UserDetailsService提供一个UserDetails对象。 像上面提到的那样,大多数程序会提供他们自己的UserDetailsService虽然一些可以使用Spring Security提供的JDBC和内存实现。 由此产生的UserDetails对象-特别是UserDetails中包含的GrantedAuthority[]-将被用来组装Authentication对象。
在验证机制重新获得了组装好的Authentication对象以后,他会认为请求有效,把Authentication放到SecurityContextHolder里,然后导致原始请求重审(第七步)。 另一方面,如果AuthenticationProvider驳回了请求,验证机制会让用户代码重试(第二步)。
5.3.4. 直接设置SecurityContextHolder的内容
虽然这表述了一个典型的验证流程,但是好消息是Spring Security不在意你如何把一个Authentication放到SecurityContextHolder里的。 唯一关键的需求是SecurityContextHolder包含Authentication,用来表现一个主体,在AbstractSecurityInterceptor之前验证请求的。
你可以(很多用户都这样做)写一个自己的过滤器或MVC控制器来提供验证系统的交互,这些都不是基于Spring Security的。 比如,你也许使用容器管理验证,从ThreadLocal或JNDI里获得当前用户信息。 或者,你的公司可能有一个遗留系统,它是一个企业标准,你不能控制它。 这种情况下,很容易让Spring Security工作,也能提供验证能力。 你所需要的就是写一个过滤器(或等价物)从指定位置读取第三方用户信息,把它放到SecurityContextHolder里。 实现这些很简单,这种整合是完全被支持的方法。
5.4. 安全对象
如果你熟悉AOP的话,就会知道有几种不同的拦截方式:之前,之后,抛异常和环绕。 其中环绕是非常有用的,因为advisor可以决定是否执行这个方法,是否修改返回的结果,是否抛出异常。 Spring Security为方法调用提供了一个环绕advice,就像web请求一样。 我们使用AOP联盟制作了一个方法调用的环绕advice,我们使用标准filter建立了对web请求的环绕advice。
对那些不熟悉AOP的人,需要理解的关键问题是Spring Security可以帮助你保护方法的调用,就像保护web请求一样。 大多数人对保护服务层里的安全方法非常按兴趣。 这是因为在目前这一代J2EE程序里,服务器放了更多业务相关的逻辑(需要澄清,作者不建议这种设计方法,作为替代的,而是应该使用DTO,集会,门面和透明持久模式压缩领域对象,但是贫血领域对象是当前的主流思路,我们会在这里讨论它)。 如果你只是需要保护服务层的方法调用,使用Spring标准AOP平台(被称作AOP联盟)就够了。 如果你想直接保护领域对象,你会发现AspectJ非常值得考虑。
可以选择使用AspectJ还是AOP联盟处理方法验证,或者你可以选择使用filter处理web请求验证。 你可以不选,选择其中一个,选择两个,或者三个都选。 主流的应用是处理一些web请求验证,再结合一些在服务层里的AOP联盟方法调用验证。
Spring Security使用"secure object"来表示任何需要安全管理的对象。 Spring Security支持的每个安全对象都有它自己的类,他们都是AbstractSecurityInterceptor的子类。 重要的是,在AbstractSecurityInterceptor运行的时候,如果主体通过了认证,SecurityContextHolder里就会包含一个合法的 Authentication。
AbstractSecurityInterceptor提供了一致的流程,来处理安全方法的请求。 这个流程包括查找分配给当前请求的"配置属性"。 这个"配置属性"可以被想像成一个字符串,对AbstractSecurityInterceptor有特殊含义。 通常使用XML配置你的AbstractSecurityInterceptor。 无论如何,AbstractSecurityInterceptor会告诉AccessDecisionManager“这里是配置属性,这里是当前Authentication对象,这里是当前Authentication对象,这里是当前请求的细节-然后,这个特定的主体,是否允许执行这个特定的操作吗?”
假设AccessDecisionManager决定允许执行这个请求,AbstractSecurityInterceptor会正常执行这个请求。 话虽如此,罕见情况下,用户可能需要把SecurityContext的Authentication换成另一个Authentication,通过访问RunAsManager。 这也许在,有原因,不常见的情况下有用,比如,服务层方法需要调用远程系统,表现不同的身份。 因为Spring Security自动传播安全身份,从一个服务器到另一个(假设你使用了配置好的RMI或者HttpInvoker远程调用协议客户端),就可以用到它了。
按照下面安全对象执行和返回的方式-可能意味着完全的方法调用或过滤器链的执行。 这种状态下AbstractSecurityInterceptor对有可能修改返回对象感兴趣。 你可能想让它发生,因为验证决定不能“关于如何在”一个安全对象调用。 高可插拔性,AbstractSecurityInterceptor通过控制AfterInvocationManager,实际上在需要的时候,修改对象。 这里类实际上可能替换对象,或者抛出异常,或者什么也不做。
因为AbstractSecurityInterceptor是中央模板类,更像第一时间为它服务。
关键"secure object"模型
Figure 5.1. 关键"secure object"模型
只有开发者才会关心使用全心的方法,进行拦截和验证请求,将直接使用安全方法。 比如,可能新建一个安全方法,控制对消息系统的权限。 安全需要的任何事情,也可以提供一种拦截的方法(好像AOP的环绕advice语法那样)有可能在安全对象里处理。 这样说的话,大多数Spring应用简单拥有三种当前支持的安全类型(AOP联盟的MethodInvocation,AspectJ JoinPoint和web请求FilterInterceptor)完全透明的。
5.5. 结论
祝贺你! 你已经看过了足够多的Spring Security的高级特性,着手于你的程序。 我们探讨了共享组件,验证是如何工作的,并审核了“安全对象”的正常验证过程。 参考指南的后面部分,可能也可能灭有满足你的特定要求,可以使用任何顺序阅读。
5.1. 运行环境
Spring Security可以运行在标准的Java 1.4运行环境下。 它也支持Java 5.0,不过这部分代码单独打包起来,放到发布的,文件名是"tiger"前缀的JAR文件里。 因为Spring Security的目标是自己容器内管理,所以不需要为你的Java运行环境进行什么特别的配置。 特别是,不需要特别配置一个Java Authentication and Authorization Service (JAAS)政策文件,也不需要把Spring Security放到server的classLoader下。
上面这些设计,确保了发布时的最大轻便性,你可以简单把你的目标文件(JAR或WAR或EAR)从一个系统复制到另一个系统,它会立即正常工作。
5.2. 共享组件
让我们展示一些Spring Security中很重要的共享组件。 被成为"shared"的组件,是指它在框架中占有很重要的位置,框架离开它们就没法运行。 这些java类表达了维持系统的构建代码块,所以理解他们的位置是非常重要的,即使你不需要直接跟他们打交道。
5.2.1. SecurityContextHolder, SecurityContext 和 Authentication对象
最基础的对象就是SecurityContextHolder。 我们把当前应用程序的当前安全环境的细节存储到它里边了。 默认情况下,SecurityContextHolder使用ThreadLocal存储这些信息,这意味着,安全环境在同一个线程执行的方法一直是有效的,即使这个安全环境没有作为一个方法参数传递到那些方法里。 这种情况下使用ThreadLocal是非常安全的,只要记得在处理完当前主体的请求以后,把这个线程清除就行了。 当然,Spring Security自动帮你管理这一切了,你就不用担心什么了。
有些程序并不适合使用ThreadLocal,因为它们处理线程的特殊方法。 比如,swing客户端也许希望JVM里的usoyou线程都使用同一个安全环境。 为了这种情况,我们而已使用SecurityContextHolder.MODE_GLOBAL。 其他程序可能想让一个线程创建的线程也使用相同的安全主体。 这时可以使用SecurityContextHolder.MODE_INHERITABLETHREADLOCAL。 想要修改默认的SecurityContextHolder.MODE_THREADLOCAL模式,可以使用两种方法。 第一个是设置系统属性。 另一个是调用SecurityContextHolder的静态方法。 大多数程序不需要修改默认值,但是如果你需要做修改,先看一下SecurityContextHolder的JavaDoc中的详细信息。
我们把安全主体和系统交互的信息都保存在SecurityContextHolder中了。 Spring Security使用一个Authentication对应来表现这些信息。 虽然你通常不需要自己创建一个Authentication对象,很常见的,用户查询Authentication对象。 你可以使用下面的代码-在你程序中的任何位置-来做这件事:
Object obj = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
if (obj instanceof UserDetails) {
String username = ((UserDetails)obj).getUsername();
} else {
String username = obj.toString();
}
上面的代码介绍了一定数量的,有趣的,几个关键对象之间的相互关系。 首先,你会注意到SecurityContextHolder 和 Authentication之间的中间对象。 这个SecurityContextHolder.getContext()方法会直接返回SecurityContext。
5.2.2. UserDetailsService
从上面的代码片段中还可以看出另一件事,就是你可以从Authentication对象中获得安全主体。 这个安全主体就是一个对象。 大多数情况下,可以强制转换成UserDetails对象。 UserDetails是一个Spring Security的核心接口。 它代表一个主体,是扩展的,而且是为特定程序服务的。 想一下UserDetails章节,在你自己的用户数据库和如何把Spring Security需要的数据放到SecurityContextHolder里。 为了让你自己的用户数据库起作用,我们常常把UserDetails转换成你系统提供的类,这样你就可以直接调用业务相关的方法了(比如getEmail(), getEmployeeNumber()等等)。
现在,你可能想知道,我应该什么时候提供这个UserDetails对象呢? 我怎么做呢? 我想你说这个东西是声明式的,我不需要写任何代码,怎么办? 简单的回答是,这里有一个特殊的接口,叫UserDetailsService。 这个接口里的唯一一个方法,接收String类型的用户名参数,返回UserDetails。 大多数验证提供器使用Spring Security代理UserDetailsService,作为验证过程的一部分。 这个UserDetailsService用来建立Authentication对象,保存在SecurityContextHolder里。 好消息是我们提供了好几个UserDetailsService实现,其中一个使用内存里的map,另一个使用JDBC。 虽然,大多数用户倾向于写自己的,使用这些实现常常放到已有的数据访问对象(DAO)上,表示它们的雇员,客户或其他企业应用中的用户。 记住这个优势,无论你用什么UserDetailsService返回的数据都可以通过SecurityContextHolder获得,就像上面的代码片段讲的一样。
5.2.3. GrantedAuthority
除了主体,另一个Authentication提供的重要方法是getAuthorities()。 这个方法提供了GrantedAuthority对象数组。 毫无疑问,GrantedAuthority是赋予到主体的权限。 这些权限通常使用角色表示,比如ROLE_ADMINISTRATOR 或 ROLE_HR_SUPERVISOR。 这些角色会在后面,对web验证,方法验证和领域对象验证进行配置。 Spring Security的其他部分用来拦截这些权限,期望他们被表现出现。 GrantedAuthority对象通常使用UserDetailsService读取的。
通常情况下,GrantedAuthority对象是应用程序范围下的授权。 它们不会特意分配给一个特定的领域对象。 因此,你不能设置一个GrantedAuthority,让它有权限展示编号54的Employee对象,因为如果有成千上网的这种授权,你会很快用光内存(或者,至少,导致程序花费大量时间去验证一个用户)。 当然,Spring Security被明确设计成处理常见的需求,但是你最好别因为这个目的使用项目领域模型安全功能。
最后,但不是最不重要的,优势你需要在HTTP请求之间共享SecurityContext. 其他时候,主体会在每个请求里重新验证,虽然大多数情况下它可以存储。 HttpSessionContextIntegrationFilter就是实现在HTTP请求之间存储SecurityContext的。 就像它的类名一样,HttpSession被用来保存这些信息。 你不应该因为安全的问题,直接与HttpSession打交道。 根本不存在这样做的理由-一直使用SecurityContextHolder作替代方式。
5.2.4. 小结
简单回顾一下,Spring Security主要是由一下几部分组成的:
*
SecurityContextHolder,提供几种访问SecurityContext的方式。
*
SecurityContext,保存Authentication信息,和请求对应的安全信息。
*
HttpSessionContextIntegrationFilter,为了在不同请求使用,把SecurityContext保存到 HttpSession里。
*
Authentication,展示Spring Security特定的主体。
*
GrantedAuthority,反应,在应用程序范围你,赋予主体的权限。
*
UserDetails,通过你的应用DAO,提供必要的信息,构建Authentication对象。
*
UserDetailsService,创建一个 UserDetails,传递一个 String类型的用户名(或者证书ID或其他)。
现在,你应该对这种重复使用的组件有一些了解了。 让我们贴近看一下验证的过程。
5.3. 验证
就像这篇指南开头提到的那样,Spring Security可在很多不同的验证环境下使用。 虽然我们推荐人们使用Spring Security,不与已存在的容器管理认证系统整合,但它也是支持的-使用你自己的属性验证系统进行整合。 让我们先看看Spring Security完全依靠自己,管理web安全,这里会演示最复杂和最常见的情况。
讨论一个典型的web应用验证过程:
1.
你访问首页,点击一个链接。
2.
向服务器发送一个请求,服务器判断你是否在访问一个受保护的资源。
3.
如果你还没有进行过认证,服务器发回一个响应,提示你必须进行认证。 响应可能是HTTP响应代码,或者是重新定向到一个特定的web页面。
4.
依据验证机制,你的浏览器将重定向到特定的web页面,这样你可以添加表单, 或者浏览器使用其他方式校验你的身份(比如,一个基本校验对话框,cookie,或者X509证书,或者其他)。
5.
浏览器会发回一个响应给服务器。 这将是HTTP POST包含你填写的表单内容,或者是HTTP头部,包含你的验证信息。
6.
下一步,服务器会判断当前的证书是否是有效的, 如果他们是有效的,下一步会执行。 如果他们是非法的,通常你的浏览器会再尝试一次(所以你返回的步骤二)。
7.
你发送的原始请求,会导致重新尝试验证过程。 有希望的是,你会通过验证,得到猪狗的授权,访问被保护的资源。 如果你有足够的权限,请求会成功。否则,你会收到一个HTTP错误代码403,意思是访问被拒绝。
Spring Security使用鲜明的类负责上面提到的每个步骤。 主要的部分是(为了使用他们)是ExceptionTranslationFilter, 一个AuthenticationEntryPoint, 一个验证机制,一个AuthenticationProvider。
5.3.1. ExceptionTranslationFilter
ExceptionTranslationFilter是一个Spring Security过滤器,用来检测是否抛出了Spring Security异常。 这些异常会被AbstractSecurityInterceptor抛出,它主要用来提供验证服务。 我们会在下一节讨论AbstractSecurityInterceptor,但是现在,我们只需要知道,它是用来生成Java异常,和知道跟HTTP没啥关系,或者如何验证一个主体。 而ExceptionTranslationFilter提供这些服务,使用特点那个的响应,返回错误代码403(如果主题被验证了,但是权限不足-在上边的步骤七),或者启动一个AuthenticationEntryPoint(如果主体没有认证,然后我们需要进入步骤三)。
5.3.2. AuthenticationEntryPoint
AuthenticationEntryPoint对应中上面列表中的步骤三。 如你所想的,每个web应用程序都有默认的验证策略(好的,这可以在Spring Security里配置一切,但是让我们现在保持简单)。 每个主要验证系统会有它自己的AuthenticationEntryPoint实现, 会执行动作,如同步骤三里的描述一样。
在你的浏览器决定提交你的认证证书之后(使用HTTP表单发送或者是HTTP头),服务器部分需要有一些东西来“收集”这些验证信息。 现在我们到了上述的第六步。 在Spring Security里,我们需要一个特定的名字,来描述从用户代码(通常是浏览器)收集验证信息的功能,这个名字就是“验证机制”。 在从用户代码哪里收集了验证细节之后,一个"Authentication 请求"对象会被AuthenticationProvider建立。
5.3.3. AuthenticationProvider
Spring Security认证过程的最后一个角色是AuthenticationProvider。 非常简单,这是跟获得Authentication请求对象相关的,决定它是否是有效的。 这个供应器或者抛出一个异常,或者返回一个完整的Authentication对象。 还记得我们的好朋友UserDetails和UserDetailsService吗? 如果不记得,回头看看前面的章节,刷新你的记忆。 大多数AuthenticationProvider都会要求UserDetailsService提供一个UserDetails对象。 像上面提到的那样,大多数程序会提供他们自己的UserDetailsService虽然一些可以使用Spring Security提供的JDBC和内存实现。 由此产生的UserDetails对象-特别是UserDetails中包含的GrantedAuthority[]-将被用来组装Authentication对象。
在验证机制重新获得了组装好的Authentication对象以后,他会认为请求有效,把Authentication放到SecurityContextHolder里,然后导致原始请求重审(第七步)。 另一方面,如果AuthenticationProvider驳回了请求,验证机制会让用户代码重试(第二步)。
5.3.4. 直接设置SecurityContextHolder的内容
虽然这表述了一个典型的验证流程,但是好消息是Spring Security不在意你如何把一个Authentication放到SecurityContextHolder里的。 唯一关键的需求是SecurityContextHolder包含Authentication,用来表现一个主体,在AbstractSecurityInterceptor之前验证请求的。
你可以(很多用户都这样做)写一个自己的过滤器或MVC控制器来提供验证系统的交互,这些都不是基于Spring Security的。 比如,你也许使用容器管理验证,从ThreadLocal或JNDI里获得当前用户信息。 或者,你的公司可能有一个遗留系统,它是一个企业标准,你不能控制它。 这种情况下,很容易让Spring Security工作,也能提供验证能力。 你所需要的就是写一个过滤器(或等价物)从指定位置读取第三方用户信息,把它放到SecurityContextHolder里。 实现这些很简单,这种整合是完全被支持的方法。
5.4. 安全对象
如果你熟悉AOP的话,就会知道有几种不同的拦截方式:之前,之后,抛异常和环绕。 其中环绕是非常有用的,因为advisor可以决定是否执行这个方法,是否修改返回的结果,是否抛出异常。 Spring Security为方法调用提供了一个环绕advice,就像web请求一样。 我们使用AOP联盟制作了一个方法调用的环绕advice,我们使用标准filter建立了对web请求的环绕advice。
对那些不熟悉AOP的人,需要理解的关键问题是Spring Security可以帮助你保护方法的调用,就像保护web请求一样。 大多数人对保护服务层里的安全方法非常按兴趣。 这是因为在目前这一代J2EE程序里,服务器放了更多业务相关的逻辑(需要澄清,作者不建议这种设计方法,作为替代的,而是应该使用DTO,集会,门面和透明持久模式压缩领域对象,但是贫血领域对象是当前的主流思路,我们会在这里讨论它)。 如果你只是需要保护服务层的方法调用,使用Spring标准AOP平台(被称作AOP联盟)就够了。 如果你想直接保护领域对象,你会发现AspectJ非常值得考虑。
可以选择使用AspectJ还是AOP联盟处理方法验证,或者你可以选择使用filter处理web请求验证。 你可以不选,选择其中一个,选择两个,或者三个都选。 主流的应用是处理一些web请求验证,再结合一些在服务层里的AOP联盟方法调用验证。
Spring Security使用"secure object"来表示任何需要安全管理的对象。 Spring Security支持的每个安全对象都有它自己的类,他们都是AbstractSecurityInterceptor的子类。 重要的是,在AbstractSecurityInterceptor运行的时候,如果主体通过了认证,SecurityContextHolder里就会包含一个合法的 Authentication。
AbstractSecurityInterceptor提供了一致的流程,来处理安全方法的请求。 这个流程包括查找分配给当前请求的"配置属性"。 这个"配置属性"可以被想像成一个字符串,对AbstractSecurityInterceptor有特殊含义。 通常使用XML配置你的AbstractSecurityInterceptor。 无论如何,AbstractSecurityInterceptor会告诉AccessDecisionManager“这里是配置属性,这里是当前Authentication对象,这里是当前Authentication对象,这里是当前请求的细节-然后,这个特定的主体,是否允许执行这个特定的操作吗?”
假设AccessDecisionManager决定允许执行这个请求,AbstractSecurityInterceptor会正常执行这个请求。 话虽如此,罕见情况下,用户可能需要把SecurityContext的Authentication换成另一个Authentication,通过访问RunAsManager。 这也许在,有原因,不常见的情况下有用,比如,服务层方法需要调用远程系统,表现不同的身份。 因为Spring Security自动传播安全身份,从一个服务器到另一个(假设你使用了配置好的RMI或者HttpInvoker远程调用协议客户端),就可以用到它了。
按照下面安全对象执行和返回的方式-可能意味着完全的方法调用或过滤器链的执行。 这种状态下AbstractSecurityInterceptor对有可能修改返回对象感兴趣。 你可能想让它发生,因为验证决定不能“关于如何在”一个安全对象调用。 高可插拔性,AbstractSecurityInterceptor通过控制AfterInvocationManager,实际上在需要的时候,修改对象。 这里类实际上可能替换对象,或者抛出异常,或者什么也不做。
因为AbstractSecurityInterceptor是中央模板类,更像第一时间为它服务。
关键"secure object"模型
Figure 5.1. 关键"secure object"模型
只有开发者才会关心使用全心的方法,进行拦截和验证请求,将直接使用安全方法。 比如,可能新建一个安全方法,控制对消息系统的权限。 安全需要的任何事情,也可以提供一种拦截的方法(好像AOP的环绕advice语法那样)有可能在安全对象里处理。 这样说的话,大多数Spring应用简单拥有三种当前支持的安全类型(AOP联盟的MethodInvocation,AspectJ JoinPoint和web请求FilterInterceptor)完全透明的。
5.5. 结论
祝贺你! 你已经看过了足够多的Spring Security的高级特性,着手于你的程序。 我们探讨了共享组件,验证是如何工作的,并审核了“安全对象”的正常验证过程。 参考指南的后面部分,可能也可能灭有满足你的特定要求,可以使用任何顺序阅读。
发表评论
-
spring security权限管理手册升级至spring security-3.1.3
2012-12-08 01:01 12298费了半天劲,终于把原来基于spring security 2. ... -
请把acegi替换成Spring Security(内附视频)
2010-03-22 09:54 6562在对web项目进行权限管理时,采用的方法无非是写一大堆JSP或 ... -
Spring Security-3.0.1中文官方文档(翻译版)
2010-01-19 09:36 10645这次发布的Spring Security-3.0.1是一个bu ... -
敬献Spring Security-3.x官方文档中文版
2009-12-29 11:43 10880Spring Security-3.x新近发布,整体的项 ... -
【分享】《基于Spring Security的ACL实现与扩展》内附ppt下载
2009-09-21 09:43 3451上次朋友间技术交流整理的ppt文档,因为之前一直在整理Spri ... -
Spring Security 安全权限管理手册(0.1.0更新)
2009-08-05 10:26 5034随着内容的堆叠,文档结构开始渐渐混乱了,到0.1.0为止关于认 ... -
Spring Security 安全权限管理手册(0.0.9更新)
2009-07-27 09:27 3279这次更新中包含了一个在用户输入密码错误三次后锁定账户的示 ... -
Spring Security 安全权限管理手册(0.0.8更新)
2009-07-20 09:58 1890Spring Security-2.0.5发布,这个bug ... -
Spring Security 安全权限管理手册(0.0.7更新)
2009-07-13 00:38 3196这一次迭代,对章节的命名进行了这里,目标是尽快覆盖Spring ... -
Spring Security 安全权限管理手册(0.0.6更新)
2009-07-10 01:54 1669这一次,我们添加了taglib标签库的时候,以及如何使用多种方 ... -
Spring Security手册更新cas, basic, acl
2009-06-29 18:13 2670这次更新的都是重头戏,CAS和ACL。其中ACL只是简述了Sp ... -
Spring Security手册更新——添加“管理会话”和对namespace,database
2009-06-22 10:04 1942新增的部分有,第八章“管理会话”,附录D,E分别整 ... -
图解Spring Security默认使用的过滤器
2009-06-15 10:38 3860第 9 章 图解过滤器 图 9.1. au ... -
Spring Security-2.0导航-基础篇,又添两章
2009-06-10 10:31 1917目前我们在基础篇中已经编写了六章,基本上可 ... -
Spring Security-2.0入门教程(基础篇)
2009-06-04 17:48 4775欢迎阅读咱们写的Spring Security教程,咱们既不想 ... -
springsecurity-2.x官方文档中文翻译初步整理完成,附上几个例子
2008-08-17 11:12 7891预览地址:http://family168.com/tutor ... -
(翻译)Spring Security-2.0.x参考文档“领域对象安全”
2008-08-13 00:18 2199领域对象安全 24.1. 概述 请注意:在2.0.0之前,S ... -
(翻译)Spring Security-2.0.x参考文档“安全对象实现”
2008-08-12 09:50 2027安全对象实现 23.1. AOP联盟 (MethodInvoc ... -
(翻译)Spring Security-2.0.x参考文档“通用授权概念”
2008-08-11 18:22 2821通用授权概念 22.1. 授权 在认证部分简略提过了,所有的 ... -
(翻译)Spring Security-2.0.x参考文档“安全数据库表结构”
2008-08-10 09:52 2035安全数据库表结构 可以为框架采用不同的数据库结构,这个附录为 ...
相关推荐
### Spring Security 2.0.x完全中文参考文档 #### 序言 本文档旨在为用户提供一份详尽且全面的Spring Security 2.0.x版本的中文指南,它不仅覆盖了核心概念、配置方法以及实际应用案例,还深入探讨了安全框架的...
这份全中文的Spring 2.0技术文档是学习和理解这一版本的重要参考资料,旨在帮助中国开发者更好地掌握Spring框架的核心概念和实践技巧。 一、Spring概述 Spring是一个开源的Java平台,主要目标是简化企业级应用开发...
具体的代码实现会涉及到微信官方API的调用,这需要参考微信开发者文档。 总的来说,微信OAuth2.0授权是连接微信生态系统的重要桥梁,它为开发者提供了便捷且安全的方式来获取和识别用户,从而实现更丰富的功能和...
Acegi是Spring Security的前身,是一款基于Spring框架的安全管理工具,旨在为应用程序提供安全控制功能,包括身份验证(Authentication)和授权(Authorization)。Acegi的核心优势在于其高度集成Spring框架的能力,...
根据提供的信息,我们可以推断这份文档“Spring2.0开发参考手册[电子书509页]”是一份详尽的指南,旨在帮助开发者更好地理解和使用Spring框架2.0版本的功能和技术。Spring框架是一个广泛使用的Java平台上的企业级...
《Spring 2.0 中文用户指南》是针对Spring框架2.0版本的一份详尽指导文档,旨在帮助开发者深入理解和高效使用这个流行的Java企业级应用框架。Spring框架以其依赖注入(Dependency Injection,DI)和面向切面编程...
### Spring Cloud Finchley.RELEASE中文参考手册知识点 #### Spring Cloud概述 Spring Cloud是基于Spring Boot的一套微服务开发工具集。它旨在加速分布式系统的开发,提供了一套简单的工具来快速实现一些常见的...
首先,"spring2.0-reference_final_zh_cn.chm"是一个中文版的Spring 2.0参考手册,对于初学者来说非常有价值。这个CHM文件通常包含了Spring框架的所有API文档,详细解释了每个类、接口和方法的功能,是深入理解...
首先,`spring2.0参考手册.chm`是Spring 2.0版本的官方参考手册,虽然现在Spring已经发展到了5.x版本,但早期的版本对于理解其设计理念和基础概念仍然很有价值。这个手册会详细解释Spring的核心特性,包括依赖注入...
### XFire开发指南知识点概述 #### 一、XFire简介 - **定义**: XFire是一个高性能的Java SOAP框架,用于构建面向服务架构(SOA)的应用程序。 - **特点**: - 支持多种标准:如SOAP、WSDL、WS-I Basic Profile、WS-...
**Spring Acegi 3 文档概述** Spring Acegi 安全框架是 Spring 框架的一个扩展,专门用于实现企业级应用的安全管理。在 Spring Acegi 3 中,它提供了全面的身份验证、授权和会话管理功能,为 Java 开发者提供了一套...
### DWR中文文档v0.9 - DWR2.0 版本介绍 #### 前言 随着Ajax技术的兴起和发展,越来越多的开发者希望能够利用这项技术为用户提供更丰富的交互体验。然而,对于许多程序员来说,如何将Ajax与现有的应用程序进行有效...
**J2EE 6官方文档概述** J2EE(Java 2 Platform, Enterprise Edition)6是Java平台上用于构建企业级应用程序的框架。这个版本引入了许多改进和简化,以提高开发效率,降低复杂性,并支持现代Web应用程序的需求。...
Activiti 支持多种安全机制,如Spring Security,可以集成到现有的企业身份验证系统中。同时,它能够与各种企业系统(如ERP、CRM)无缝集成,实现流程自动化。 通过深入研究"activiti6.0.0",开发者不仅可以掌握...