[转帖]《Spring Security3》第六章第四部分翻译(异常处理)_Android, Python及开发编程讨论区_Weblogic技术|Tuxedo技术|中间件技术|Oracle论坛|JAVA论坛|Linux/Unix技术|hadoop论坛_联动北方技术论坛  
网站首页 | 关于我们 | 服务中心 | 经验交流 | 公司荣誉 | 成功案例 | 合作伙伴 | 联系我们 |
联动北方-国内领先的云技术服务提供商
»  游客             当前位置:  论坛首页 »  自由讨论区 »  Android, Python及开发编程讨论区 »
总帖数
1
每页帖数
101/1页1
返回列表
0
发起投票  发起投票 发新帖子
查看: 4027 | 回复: 0   主题: [转帖]《Spring Security3》第六章第四部分翻译(异常处理)        下一篇 
fozhyn
注册用户
等级:上士
经验:317
发帖:101
精华:0
注册:2011-10-18
状态:离线
发送短消息息给fozhyn 加好友    发送短消息息给fozhyn 发消息
发表于: IP:您无权察看 2011-10-19 15:12:33 | [全部帖] [楼主帖] 楼主

理解和配置异常处理

    Spring Security使用简单的分发器模式将框架抛出的异常转移到明确的处理行为中,这将会影响用户对安全资源的访问。Spring Security过滤器链中最后几个过滤器之一的o.s.s.web.access.ExceptionTranslationFilter负责检查在认证和授权过程中(在过滤器链的最后一个过滤器即FilterSecurityInterceptor里)抛出的异常并采取适当的行为。

    标准的ExceptionTranslationFilter支持分发处理三种常规类型的失败,如下图所示:

北京联动北方科技有限公司
 我们能够看到ExceptionTranslationFilter处理如下的场景:

l  抛出AuthenticationException异常,用户需要登录(在大多数场景下——取决于AuthenticationEntryPoint,我们将会在本章稍后介绍);

l  抛出AccessDeniedException,用户已经尚未登录;

l  抛出AccessDeniedException,用户已经登录,在这种场景下,展现给用户的要么是出错页面,要么是通用的HTTP 403响应。

让我们看一下AccessDeniedHandler的配置。

配置“Access Denied”处理

    到此为止,当一个认证过的用户访问受保护的资源时,因为缺少GrantedAuthority或其它需要的权限被拒绝的时候,他们看到的是servlet容器的默认HTTP 403(访问拒绝)页面。这个页面是o.s.s.web.access.AccessDeniedHandler默认行为的结果,它被ExceptionTranslationFilter所触发以响应框架抛出的一个AccessDeniedException异常。

    尽管这个简单的出错页面有效,但是并不具有吸引力和也不对用户友好。最好能够将这个页面与我们站点整体的外观和风格一致,并为用户提供信息告诉他发生了什么。

    基本的处理用户访问拒绝报告的方法是配置自定义的URL,Spring Security会在请求拒绝时,将用户带到这个URL。我们会发现这个功能与初始登录时,用户被定向到<form-login>元素声明的 login-page很类似。

配置“Access Denied”的目标地址


 配置用户被定向到的地址是这个练习中最简单的部分。只需在<http>声明中,添加一个元素<access-denied-handler>,它指明了我们的访问拒绝处理URL,如下:


Xml代码   北京联动北方科技有限公司


<http auto-config="true" ...>
<access-denied-handler error-page="/accessDenied.do"/>
</http>


 注意——还没完事呢,因为我们还没有将这个URL与任何的Spring MVC应用代码关联起来。我们需要在LoginLogoutController添加增强代码以处理这个URL,并推送一些有用的信息到model中供view展现给用户。

添加对AccessDeniedException处理的控制器


    我们需要添加一个控制器action处理方法以响应刚刚配置的URL。另外,我们会从AccessDeniedException抽取一些细节信息,这可能在用户看到我们自定义访问拒绝页面时有用。

Java代码   北京联动北方科技有限公司


@Controller
public class LoginLogoutController extends BaseController{
      // Ch 6 Access Denied
      @RequestMapping(method=RequestMethod.GET, value="/accessDenied.do").
      public void accessDenied(ModelMap model, HttpServletRequest request) {
            AccessDeniedException ex = (AccessDeniedException)
            request.getAttribute(AccessDeniedHandlerImpl
            .SPRING_SECURITY_ACCESS_DENIED_EXCEPTION_KEY);
            StringWriter sw = new StringWriter();
            model.addAttribute("errorDetails", ex.getMessage());
            ex.printStackTrace(new PrintWriter(sw));
            model.addAttribute("errorTrace", sw.toString());
      }
}


 注意的是,需要引用AccessDeniedHandlerImpl来获取request中指定名字的属性,它被用来临时存储当前request范围内的异常。

    遗憾的是,AccessDeniedException并没有在它的message中提供足够的细节信息,而这对系统管理员和用户本身可能会有用。你可能会对使用Spring Security的AccessDeniedException感兴趣或者可能扩展它以提供更多的上下文信息,以得到当授权检查不通过时用户正在试图进行什么操作。

编写Access Denied页面


    控制器写好后,接下来是访问拒绝页面。

Html代码   北京联动北方科技有限公司


<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<jsp:include page="common/header.jsp">
<jsp:param name="pageTitle" value="Access Denied"/>
</jsp:include>
<h1>Access Denied</h1>
<p>
Access to the specified resource has been denied for
the following reason: <strong>${errorDetails}</strong>.
</p>
<em>Error Details (for Support Purposes only):</em><br />
<blockquote>
<pre>${errorTrace}</pre>
</blockquote>
<jsp:include page="common/footer.jsp"/>


          你可以看到我们使用了在控制器设置的模型属性errorDetails和errorTrace。尽管不是很漂亮,但是这个页面完成了它的任务即用通用的站点导航,将用户带到了站点的其它区域并给他们提供了导致出错的提示信息。

什么会触发AccessDeniedException

    当设计异常处理时,进行一些分析并理解目标异常的原理很重要。对于Spring Security的用户来说,通常很迷惑的一件事就是AccessDeniedException(默认会导致HTTP 403页面)和AuthenticationException(一般当用户根本没有登录时抛出)。以下的指南可能会帮助你分清框架在什么时间抛出每种类型的异常:

异常类型

谁抛出以及原因

AuthenticationException


AuthenticationProvider,当提供的凭证不合法或用户失效、过期;

DaoAuthenticationProvider,当访问DAO数据存储时出错;

RememberMeServices,当remember me cookie被篡改;

各种特定的认证类(CAS、NTLM等)在用户特定的场景下。

AccessDeniedException


AccessDecisionManager,当配置的Voter投票拒绝访问——注意这可能在任何投票场景下

    要记住的是,我们前面提到的ExceptionTranslationFilter是区分这两种类型异常的关键点,因为这关系到应用用户的请求和响应流程。

【注意过滤器链中在ExceptionTranslationFilter之前的那些过滤器。ExceptionTranslationFilter只会处理和响应过滤器链中在此之后的过滤器所抛出的异常。用户可能会感到迷惑,尤其是将自定义过滤器进行了不正确排序的时候,不明白为什么期望的行为与应用实际的异常处理不一致——在很多场景下,过滤器的顺序是原因所在。】

    尽管内置的处理流程在大多数情况下是可预测且满足需要的,但有时候你会需要自定义异常处理,尤其是在引入基类异常的自定义子类时,这需要过滤器链的特殊处理。

AuthenticationEntryPoint的重要性

    AuthenticationEntryPoint(在ExceptionTranslationFilter我们看到它是工作流程中的一个辅助类)在处理未认证用户请求中很重要。当ExceptionTranslationFilter确定用户需要认证时,它请求AuthenticationEntryPoint以了解下一步要做什么。在基于form的认证中,o.s.s.web.authentication.LoginUrlAuthenticationEntryPoint负责将用户定向到登录form。

    我们将会在后面的章节中看到AuthenticationEntryPoint被用在各种认证机制中,从而实现更个性化的行为——例如,在中心认证服务(CAS)单点登录中,AuthenticationEntryPoint要确保用户被定向到CAS门户进行认证。

    在很多环境下,当实现Spring Security与第三方认证系统(独立于web应用)集成时,你需要实现自己的AuthenticationEntryPoint。




赞(0)    操作        顶端 
总帖数
1
每页帖数
101/1页1
返回列表
发新帖子
请输入验证码: 点击刷新验证码
您需要登录后才可以回帖 登录 | 注册
技术讨论