处理Spring Security中的自定义exception
我们正在使用spring MVC + spring security + hibernate创建一个RESTful API。 API可以生成JSON和HTML。 为弹簧安全做一个好的error handling让我很头疼:
身份validation可以通过各种方式进行:BasicAuth,通过POST请求中的不同参数以及Web登录。 对于每个身份validation机制,在spring security xml config的 namespace元素中声明了一个filter。
我们在自定义HandlerExceptionResolver
处理所有springexception。 这适用于我们的控制器中抛出的所有exception,但我不知道如何处理自定义spring安全filter中引发的自定义exception。 由于spring安全filter在我们调用任何控制器之前到来,因此我们没有看到我们在自定义spring安全filter中抛出的exception。
我在stackoverflow上找到了这个问题: 在Spring Security中使用自定义exception 。 但是我不明白他们在哪里处理那里抛出的exception。 我们尝试了这种方法,但我们没有调用自定义的HandlerExceptionResolver
。 而是向用户呈现由tomcat呈现的丑陋堆栈跟踪。
我们为什么需要这个? 可以激活和停用用户。 如果它们被停用并尝试执行某些操作,我们希望返回带有自定义错误消息的JSON。 这应该与spring security抛出AccessDeniedException
时显示的内容不同。 AccessDeniedException
以某种方式使它成为我们的HandlerExceptionResolver
,但我无法完全遵循。
可能的解决方案我们考虑过使用ExceptionTranslationFilter
,但是当我们抛出自定义exception(在doFilter()方法的catch语句中设置断点)时,不会调用它。 在我的理解中,应该调用这个catch块,并且应该使用认证入口点。
另一种可能性:我们可以在spring安全filter链中执行与ExceptionTranslationFilter
类似的操作,并执行与AccessDeniedHandler
类似的操作:
RequestDispatcher dispatcher = request.getRequestDispatcher(errorPage); dispatcher.forward(request, response);
我们可以在请求中添加一些参数(错误代码,原因等)并让它指向一个控制器,它将处理JSON或HTML中的渲染。
以下是我们配置的简短摘录:
春季安全:
HandlerExceptionResolver的AppConfig
@Bean public HandlerExceptionResolver handlerExceptionResolver(){ logger.info("creating handler exception resolver"); return new AllExceptionHandler(); }
我们的自定义HandlerExceptionResolver
public class AllExceptionHandler implements HandlerExceptionResolver { private static final Logger logger = LoggerFactory .getLogger(AppConfig.class); @Override public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { // This is just a snipped of the real method code return new ModelAndView("errorPage"); }
我们其中一个filter的相关部分:
try { Authentication authResult = authenticationManger.authenticate(authRequest); SecurityContextHolder.getContext().setAuthentication(authResult); } catch(AuthenticationException failed) { SecurityContextHolder.clearContext(); throw failed; }
在web.xml
contextClass org.springframework.web.context.support.AnnotationConfigWebApplicationContext contextConfigLocation xxx.xxx.xxx.config spring.profiles.default LIVE org.springframework.web.context.ContextLoaderListener appServlet org.springframework.web.servlet.DispatcherServlet contextConfigLocation 1 10000000 appServlet / openEntityManagerInViewFilter org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter openEntityManagerInViewFilter /* springSecurityFilterChain org.springframework.web.filter.DelegatingFilterProxy springSecurityFilterChain /* 404 /handle/404
有没有人对我们如何解决这个问题有任何指示? 我查看了谷歌上的许多文章,其中大多数描述了当没有filter能够validation请求时如何处理spring安全性抛出的AccessDeniedException。
我们使用的是Spring Security 3.1.0和spring web mvc 3.1.0。
重要的是要记住Spring Security中filter的顺序很重要。
来自Spring Security 3的书:
ExceptionTranslationFilter
将只能处理和响应filter链执行堆栈中在其下面抛出的exception。 用户经常会感到困惑,特别是在以不正确的顺序添加自定义filter时,为什么预期的行为与他们的应用程序的实际exception处理不同 – 在许多情况下,filter的顺序是罪魁祸首!
如果您的filter是关于授权的,那么最好将它们放在链的末尾,因为默认授权filter使用此方法。 这样你就不必重新发明轮子了。
标准filter: 文档中的表
正确配置filter链后,您可以配置错误页面,甚至自定义处理程序。 文档中提供了更多信息。
我看到ExceptionTranslationFilter只处理两个exceptionAuthenticationException和AccessDeniedException以及这两个exception的自定义处理程序,那么任何其他类型的exception甚至运行时exception呢?
你将如何处理/拦截Springfilter堆栈中的任何exception? 是不是有任何Spring标准的方法来捕获和获取请求(除了在所有内容之上编写自定义filter),响应而不是在所有内容上编写另一个filter?
好吧,我最后在顶部添加了另一个filter(或者在web.xml中为/ *配置filter),它只是尝试了catch块并将任何未捕获的exception委托给自定义exception处理程序Spring组件调用ExceptionController方法(每个方法都返回以不同方式的不同响应类型)以故障安全方式还返回基于exception类型(我们的要求)的自定义exception消息。 唯一的缺点是添加一些逻辑,所以你不会继续循环。 控制器中的Spring自定义ExceptionHandlerExceptionResolver和@ExceptionHandler不处理filterexception,并且对如何将exception消息返回的限制(XML / JSON,重定向,转发,….)。 这假设您具有良好的Application Exception层次结构,该层次结构捕获exception并使用合理的引用信息抛出它们,因为filter没有任何内容。
对于错误代码,在web.xml中定义静态页面,但通过将filter映射到ERROR调度程序并为显示错误代码的页面准备模型来捕获它们。
- 使用javax.sound.sampled.Clip在游戏中播放,循环和停止多个声音。 意外错误
- 如何监视其他Java应用程序生成的exception或错误?
- 连接Java-MySql:不允许公钥检索
- 如何使用失败的xsdvalidation获取xml文件的元素和无效的xml文件
- 如何调试ConcurrentModificationException?
- Integer.parse(String str)java.lang.NumberFormatException:错误
- 在Java中编写“exception驱动开发”的性能成本?
- Java数组索引以某种方式超出界限?
- Java:catch的意义(最终的SomeException e)?