3

我正在尝试将基于 Oauth for Spring Security 的 Oauth2 客户端从普通 Java/Spring 移植到 Grails,但遇到了问题。问题的症结似乎在于 Spring Oauth 客户端实现的设计依赖于这样一个假设,即从 Oauth2RestTemplate 抛出的异常将被 OAuth2ClientContextFilter 的 catch 块捕获,从而允许过滤器发出重定向响应(向宣誓提供者发送授权请求)。

这在普通的 Java/Spring 中运行良好,但在 Grails 中,GrailsDispatcherServlet 被配置为通过 HandlerExceptionResolvers 处理所有异常。因此,在 Oauth2RestTemplate 中抛出的异常(在 Grails 控制器中调用)被 GrailsExceptionResolver 捕获,并且不会被 OAuth2ClientContextFilter 看到,从而破坏了所需的重定向行为。

我发现的所有关于定制 Grails 异常处理的讨论似乎都假设定制的目的是将异常映射到 HTTP 错误代码或错误页面视图。但是有什么方法可以告诉 Grails 简单地允许一个特定的异常通过未处理的流,以便它可以被 servlet 过滤器捕获?或者是否可以插入一个重新抛出异常而不是返回 ModelAndView 的自定义 HandlerExceptionResolver(正如对 HandlerExceptionResolver 的标准期望)?还是有其他更好的方法可以让 Oauth for Spring Security 客户端在 Grails 中工作?

4

2 回答 2

1

我认为您可以通过定义自定义异常解析器来声明exceptionHandlerresources.groovy这个自定义异常解析器可以(可选地)覆盖 GrailsExceptionResolver

exceptionHandler(MyExceptionResolver) {
    exceptionMappings = ['java.lang.Exception': '/error']
}

class MyExceptionResolver extends GrailsExceptionResolver {
     @Override
     ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, 
      Object    handler, Exception ex) {
     //your custom code
     return super.resolveException(request, response, handler, ex)
    }
}
于 2014-08-11T14:04:05.060 回答
1

这就是我最终想出的。不确定这是否是最好的解决方案,但它似乎有效:

  1. 创建一个新的 MyDispatcherServlet.groovy:

    package org.example.com
    
    import org.codehaus.groovy.grails.web.servlet.GrailsDispatcherServlet
    import javax.servlet.http.HttpServletRequest
    import javax.servlet.http.HttpServletResponse
    import org.springframework.web.servlet.ModelAndView
    import org.springframework.security.oauth2.client.UserRedirectRequiredException
    
    class MyDispatcherServlet extends GrailsDispatcherServlet {
    
        @Override
        protected ModelAndView processHandlerException(HttpServletRequest request, 
          HttpServletResponse response, Object handler, Exception ex) throws Exception {
            def e = ex
            while (e) {
                if (e instanceof UserRedirectRequiredException) {
                    throw ex
                }
                e = e.cause
             }
             return super.processHandlerException(request, response, handler, ex)                                     
         }
    }
    
  2. 运行grails install-templates并修改 web.xml 以使用 MyDispatcherServlet 而不是默认的 GrailsDispatcherServlet

结果是 MyDispatcherServlet 将重新抛出一个包含 UserRedirectRequiredException 的异常,以便它可以被 OAuth2ClientContextFilter 捕获,但其他异常将像以前一样由 GrailsExceptionResolver 传递和处理。

于 2012-07-03T15:32:58.273 回答