2012-06-29 27 views
1

我試圖將基於Oauth的Oauth2客戶端從普通的Java/Spring移植到Grails,並且遇到了問題。問題的癥結似乎在於Spring Oauth客戶端實現的設計依賴於這樣的假設:從Oauth2RestTemplate拋出的異常將被捕獲到OAuth2ClientContextFilter的catch塊中,從而允許篩選器發出重定向響應(向誓言提供者發送授權請求)。如何繞過Grails異常處理,以便使用Spring Oauth2?

這在普通Java/Spring中正常工作,但在Grails中,GrailsDispatcherServlet被配置爲通過HandlerExceptionResolvers處理所有異常。因此,GrailsExceptionResolver會捕獲Oauth2RestTemplate中引發的異常(在Grails控制器中調用),並且OAuth2ClientContextFilter永遠不會看到該異常,從而破壞了所需的重定向行爲。

我發現所有關於定製Grails異常處理的討論似乎都假定定製的目的是將異常映射到HTTP錯誤代碼或錯誤頁面視圖。但是有沒有什麼方法可以讓Grails簡單地讓一個特定的異常流經未處理的,以便它可以被servlet過濾器捕獲?或者是否可以插入自定義的HandlerExceptionResolver來重新引發異常,而不是返回ModelAndView(如HandlerExceptionResolver的標準期望)?或者還有其他更好的方法讓Grails中的Spring Security客戶端使用Oauth嗎?

回答

0

這是我最終想出來的。不知道這是最好的解決方案,但它似乎工作:

  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安裝模板和修改web.xml使用MyDispatcherServlet而不是默認的GrailsDispatcherServlet

結果是MyDispatcherServlet將重新拋出包含UserRedirectRequiredException,這樣的例外它可以被OAuth2ClientContextFilter捕獲,但其他異常將被傳遞並由GrailsExceptionResolver像以前一樣處理。

0

我認爲您可以通過定義您的自定義異常解析器來聲明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) 
    } 
}