Spring - 3.0.1 - 中文官方文档

2026/1/17 20:22:52

throw new BadCredentialsException(\} }

这里我们写了一些程序,询问用户输入一个用户名和密码, 然后执行上面的顺序。我们实 现的AuthenticationManager 会验证所有用户名和密码一样的用户。它为每个永固分配 一个单独的角色。上面输出的信息将会像这样: Please enter your username: bob

Please enter your password: password

Authentication failed: Bad Credentials Please enter your username: bob

Please enter your password: bob

Successfully authenticated. Security context contains: \\

org.springframework.security.authentication.UsernamePasswordAuthenticationToken@441d0230: \\

Principal: bob; Password: [PROTECTED]; \\ Authenticated: true; Details: null; \\ Granted Authorities: ROLE_USER 注意,你没必要写这些代码。这些处理都是发生在内部的, 比如在一个web 验证过滤器中。 我们只是使用了这些代码, 来演示真实情况下的问题,Spring Security 提供了一个简单 的答案。一个用户被验证,当SecurityContextHolder 包含了完整的Authentiation 对象。

5.3.2. 直接设置SecurityContextHolder的内容

实际上, Spring Security 不知道你怎么把Authentication 对象放到

SecurityContextHolder 里。唯一关键的要求是SecurityContextHolder 包含了一个 Authentication 表示了一个主体, 在AbstractSecurityInterceptor 之前(我们以后会 看到更多) 需要验证一个用户操作。

你可以(许多人都这样做)写自己的过滤器,或MVC 控制器来提供验证系统,不基于Spring Security。比如你可能使用容器管理的验证,让当前用户有效在TheadLocal 或JNDI 位置。或者你可能为一个公司工作,你没有什么控制力。这种情况下,使用Spring Security 很简单, 还是提供验证功能。你需要做的是些一个过滤器(或什么设备) 从一个地方读 取第三方用户信息, 构建一个Spring Security 特定的Authentication 对象, 把它放到 SecurityContextHolder 里。

如果你想知道AuthenticationManager 是如何实现的, 我们会在***看到。 5.4. 在web应用中验证

现在让我们研究一下情景,当我们在web 应用中使用Spring Security (不使用web.xml 安全)。一个用户如何验证,安全环境如何创建? 考虑一个典型的web 应用的验证过程: 你访问主页,点击链接。

一个请求发送给服务器,服务器决定你是否在请求一个被保护的资源。

如果你还没有授权,服务器发回一个相应,提示你必须登录。响应会是一个HTTP 响应代 码, 或重定向到特定的web 页面。

基于验证机制,你的浏览器会重定向到特殊的web 页面, 所以你可以填写表单,或者浏览 器会验证你的身份(通过一个BASIC 验证对话框,一个cookie,一个X.509 验证,等 等)。

浏览器会发送回一个响应到服务器。这会是一个HTTP POST 包含你填写的表单中的内容, 或者一个HTTP 头部包含你的验证细节。

下一步,服务器决定,当前证书是否有效。如果它们有效,下一步会执行。如果它们无效, 通常你的浏览器会被询问再试一次(所以initial 返回上两步)。

你的原始请求会引发验证过程。希望你验证了获得了授予的权限来访问被保护的资源。如 果你完允许访问,请求会成功。否则,你会收到一个HTTP 错误代码403,意思是“拒绝访 问”。

Spring Security 拥有不同的泪,对应很多常用的上面所说的步骤。主要的部分(使用的 次序)是ExceptionTranslationFilter, 一个AuthenticationEntryPoint 和一个“验证 机制”, 对应着AuthenticationManager 的调用我们在上一章见过。 5.4.1. ExceptionTranslationFilter

ExceptionTranslationFilter 是一个Spring Security 过滤器负责检测任何一个Spring Security 抛出的异常。这些异常会被AbstractSecurityInterceptor 抛出, 这是一个验 证服务的主要提供器。我们会在下一章讨论AbstractSecurityInterceptor, 而现在我们 需要知道它产生Java 异常, 不知道HTTP,也不知道如何验证一个主体。对应的

ExceptionTranslationFilter 负责这个服务, 特别负责返回错误代码403(如果主体已经 通过授权,但是权限不足- 像上面的第七步),或者启动一个AuthenticationEntryPoint (如果主体还没有授权,因此我们会进入上面的第三步)。 5.4.2. AuthenticationEntryPoint

AuthenticationEntryPoint 负责上面的步骤三。像你想的那样,每个web 应用会有一个 默认的验证策略(好,这可能像其他东西一样在Spring Security 里配置, 但现在让我 们保持简单)。每个主要的验证系统会有他们自己的AuthenticationEntryPoint 实现, 典 型的执行一个动作,描述在第三步。 5.4.3. 验证机制

一旦你的浏览器提交了你的验证证书(像HTTP 表单POST 或者HTTP 头) 这些需要一些 服务器的东西保存这些权限信息。但是现在我们进入上面的第六步。在Spring Security 中我们有一个特定的名称,为了收集验证信息的操作。从一个用户代码中(通常是浏览器), 引用它作为一个“验证机制”。例子是基于表单的登录和BASIC 验证。一旦验证细节被从 用户代理处收集到, 一个Authentication 请求对象就会被建立, 然后放到 AuthenticationManager。

在验证机制获得完全的Authentication 后,它会认为请求合法, 把Authentication 放 到SecurityContextHolder 里,然后让原始请求重试(上面第七步)。如果,其他可能, AuthenticationManager 拒绝了请求, 请求机制会让用户代理重试(上面第二步)。 5.4.4. 在请求之间保存SecurityContext。

依照应用类型,这里需要一个策略, 在用户操作之间保存安全环境。在一个典型的web 应用中, 一个用户日志,一次或顺序被它的session id。服务器缓存主体信息在session 整个过程中, 在Spring Security 中, 保存SecurityContext , 从请求失败

SecurityContextPersistenceFilter,默认保存到HttpSession 里的一个属性,在HTTP 请求之间。它重新保存环境到SecurityContextHolder,为每个请求。然后为每个请求

清空SecurityContextHolder。你不应该为了安全目的,直接操作HttpSession。这里 有简单的方法实现- 一直使用SecurityContextHolder 代替。

很多其他类型的应用(比如,一个无状态的REST web 服务)不会使用HTTP 会话,会在 每次请求时,重新验证。然而,这对SecurityContextPersistenceFilter 也很重要,确保 包含在SecurityContextHolder 中,在每次请求后清空。 Note

在一个单一会话接收同步请求的应用里,相同的SecurityContext 实例会在线程之间共 享。即使使用一个ThreadLocal,也是使用了来自HttpSession 的相同实例。如果你希望 暂时改变一个线程的上下文就会造成影响。如果你只是使用

SecurityContextHolder.getContext().setAuthentication(anAuthentication), 然后 Authentication 对象会反应到所有并发线程,共享相同的SecurityContext 实例。你可 以自定义SecurityContextPersistenceFilter 的行为来创建完全新的一个线程避免影响 其他的。还可以选择的是,你可以创建一个新实例,只在你暂时修改上下文的时候。这个 方法SecurityContextHolder.createEmptyContext()总会返回一个新的上下文实例。 5.5. Spring Security中的访问控制(验证)

主要接口,负责访问控制的决定,在Spring Security 中是AccessDecisionMananger。 它有一个decide 方法,可以获得一个Authentication 对象。展示主体的请求权限, 一 个“secure object”(看下边)和一个安全元数据属性队列, 为对象提供了(比如一个角 色列表,为访问被授予的请求)。 5.5.1. 安全和AOP建议

如果你熟悉AOP 的话,就会知道有几种不同的拦截方式:之前,之后,抛异常和环绕。其 中环绕是非常有用的,因为advisor 可以决定是否执行这个方法,是否修改返回的结果, 是否抛出异常。Spring Security 为方法调用提供了一个环绕advice,就像web 请求一 样。我们使用Spring 的标准AOP 支持制作了一个处理方法调用的环绕advice,我们使 用标准filter 建立了对web 请求的环绕advice。

对那些不熟悉AOP 的人,需要理解的关键问题是Spring Security 可以帮助你保护方法的 调用,就像保护web 请求一样。大多数人对保护服务层里的安全方法非常按兴趣。这是 因为在目前这一代J2EE 程序里,服务器放了更多业务相关的逻辑(需要澄清,作者不建议 这种设计方法,作为替代的,而是应该使用DTO,集会,门面和透明持久模式压缩领域对 象,但是使用贫血领域对象是当前的主流思路,所以我们还是会在这里讨论它)。如果你只 是需要保护服务层的方法调用,Spring 标准AOP 平台(一般被称作AOP 联盟)就够了。 如果你想直接保护领域对象,你会发现AspectJ 非常值得考虑。

可以选择使用AspectJ 还是Spring AOP 处理方法验证,或者你可以选择使用filter 处理 web 请求验证。你可以不选,选择其中一个,选择两个,或者三个都选。主流的应用是 处理一些web 请求验证,再结合一些在服务层里的Spring AOP 方法调用验证。 5.5.2. 安全对象和AbstractSecurityInterceptor

所以,什么是“secure object”? Spring Security 使用应用任何对象,可以被安全控制 (比如一个验证决定)提供到它上面。最常见的例子是方法调用和web 请求。 Spring Security 支持的每个安全对象类型都有它自己的类型, 它们都是

AbstractSecurityInterceptor 的子类。很重要的是,如果主体是已经通过了验证,在 AbstractSecurityInterceptor 被调用的时候,SecurityContextHolder 将会包含一个有 效的Authentication。

AbstractSecurityInterceptor 提供了一套一致的工作流程,来处理对安全对象的请求, 通常是:

查找当前请求里分配的\配置属性\。

把安全对象,当前的Authentication 和配置属性,提交给AccessDecisionManager,来 进行以此认证决定。

有可能在调用的过程中,对Authentication 进行修改。 允许安全对象进行处理(假设访问被允许了)。

在调用返回的时候执行配置的AfterInvocationManager。 5.5.2.1. 配置属性是什么?

一个\配置属性\可以看做是一个字符串,它对于AbstractSecurityInterceptor 使用的类 是有特殊含义的。它们通过框架中的ConfigAttribute 接口表现。它们可能是简单的角 色名称或拥有更复杂的含义,这就与AccessDecisionManager 实现的先进程度有关了。 AbstractSecurityInterceptor 和配置在一起的SecurityMetadataSource 用来为一个安 全对象搜索属性。通常这个属性对用户是不可见的。配置属性将以注解的方式设置在受保 护方法上,或者作为受保护URL 的访问属性。比如,当我们查看一些像 在命名空间介绍里,这就是在说 这些配置属性ROLE_A 和ROLE_B 应用到web 请求匹配到指定的模式中。实际上,使 用默认的AccessDecisionManager 配置,这意味着任何人拥有GrantedAuthority 匹 配任何这些两个属性中的一个会被允许访问。严格意义上,他们只是树形,解释是基于 AccessDecisionManager 实现的。前缀ROLE_的使用标记了这些属性是角色,会被

Spring Security 的RoleVoter 处理。它只与基于角色的AccessDecisionManager 有关。 我们会在验证章节看到AccessDecisionManager 是如何实现的。 5.5.2.2. RunAsManager

假设AccessDecisionManager 决定允许执行这个请求,AbstractSecurityInterceptor 会正常执行这个请求。话虽如此,罕见情况下,用户可能需要把SecurityContext 的 Authentication 换成另一个Authentication,通过访问RunAsManager。这也许在,

有原因,不常见的情况下有用,比如,服务层方法需要调用远程系统,表现不同的身份。因 为Spring Security 自动传播安全身份,从一个服务器到另一个(假设你使用了配置好的 RMI 或者HttpInvoker 远程调用协议客户端),就可以用到它了。 5.5.2.3. AfterInvocationManager

按照下面安全对象执行和返回的方式-可能意味着完全的方法调用或过滤器链的执行。这种 状态下AbstractSecurityInterceptor 对有可能修改返回对象感兴趣。你可能想让它发 生, 因为验证决定不能“ 关于如何在” 一个安全对象调用。高可插拔性,

AbstractSecurityInterceptor 通过控制AfterInvocationManager,实际上在需要的时 候,修改对象。这里类实际上可能替换对象,或者抛出异常,或者什么也不做。

AbstractSecurityInterceptor 和相关对象展示在Figure 5.1, “关键\模型”中。

Figure 5.1. 关键\模型 5.5.2.4. 扩展安全对象模型

只有开发者才会关心使用全心的方法,进行拦截和验证请求,将直接使用安全方法。比如, 可能新建一个安全方法,控制对消息系统的权限。安全需要的任何事情,也可以提供一种 拦截的方法(好像AOP 的环绕advice 语法那样)有可能在安全对象里处理。这样说的话, 大多数Spring 应用简单拥有三种当前支持的安全类型(AOP 联盟的MethodInvocation, AspectJ JoinPoint 和web 请求FilterInterceptor)完全透明的。 5.6. 国际化

Spring Security 支持异常信息的国际化,最终用户希望看到这些信息。如果你的应用被


Spring - 3.0.1 - 中文官方文档.doc 将本文的Word文档下载到电脑
搜索更多关于: Spring - 3.0.1 - 中文官方文档 的文档
相关推荐
相关阅读
× 游客快捷下载通道(下载后可以自由复制和排版)

下载本文档需要支付 10

支付方式:

开通VIP包月会员 特价:29元/月

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信:xuecool-com QQ:370150219