如何绕过 Grails 异常处理以使用 Spring Oauth2?
Posted
技术标签:
【中文标题】如何绕过 Grails 异常处理以使用 Spring Oauth2?【英文标题】:How can I bypass Grails exception handling, in order to use Spring Oauth2? 【发布时间】:2012-06-30 23:49:29 【问题描述】:我正在尝试将基于 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 中工作?
【问题讨论】:
【参考方案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)
运行 grails install-templates 并修改 web.xml 以使用 MyDispatcherServlet 而不是默认的 GrailsDispatcherServlet
结果是 MyDispatcherServlet 将重新抛出一个包含 UserRedirectRequiredException 的异常,以便它可以被 OAuth2ClientContextFilter 捕获,但其他异常将像以前一样由 GrailsExceptionResolver 传递和处理。
【讨论】:
【参考方案2】:我认为您可以通过定义自定义异常解析器在resources.groovy
中声明exceptionHandler
。这个自定义异常解析器可以(可选)覆盖 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)
【讨论】:
以上是关于如何绕过 Grails 异常处理以使用 Spring Oauth2?的主要内容,如果未能解决你的问题,请参考以下文章
在 Grails (GORM) 中处理并发修改,同时避免过时对象异常
如何在 Grails 单元测试中使用 Spock 模拟 passwordEncoder