2012-12-11 36 views
3

我有Spring安全性由Spring Security處理的Spring MVC應用程序。如何在Spring MVC-Spring安全應用程序中處理GWT RPC調用中的會話過期異常

UI是使用GWT構建的,它使用RPC方法從服務器獲取數據。

我需要在UI上處理會話過期的情況: 例如,RPC AsyncCallback可以獲取SessionExpiredException類型的異常,並彈出窗口,顯示消息如「您的會話已過期,請單擊刷新鏈接」等。

有人處理這樣的問題嗎?

謝謝。

回答

1

我研究了一下,這裏http://code.google.com/p/gspring/source/browse/#svn%2Ftrunk%2Fsample%2Fsession-expired%253Fstate%253Dclosed上傳的溶液。

使用mvn jetty:run-war看到演示檢查出來後,去rpc-security-sample/index.htm

有兩種方法來解決這個問題

第一是圍繞通過委託代理爲GWT RemoteServlet其中方法調用期間拋出SessionExpiredException。這需要在每個RPC服務方法中聲明Exception。例如:http://code.google.com/p/gspring/source/browse/#svn%2Ftrunk%2Fsample%2Fsession-expired%253Fstate%253Dclosed

步驟:

  1. 開發新的過濾器,其截取第一

  2. 在其中可以繼承RuntimeException爲了簡單(不需要遵循此在實施者)每個RPC方法服務聲明SessionExpiredException

  3. 開發父級通用AsyncCallback處理程序

  4. 使用http://code.google.com/p/gspring/解決方案來處理所有傳入的RCP請求。

第二這是更簡單:返回401 HTTP錯誤,並在UI側把手(GWT本地一般例外包含HTTP狀態編號)。示例:http://code.google.com/p/gspring/source/browse/#svn%2Ftrunk%2Fsample%2Fsession-expired-401

第二種方法最簡單,不需要在服務方法合同中聲明Exception。然而,第一種方法可以給你一些靈活性:它可以包含一些額外的信息,如上次登錄時間(對於SessionExpiredException)等等。另外,第二種方法可以引入新的例外,它們從SecurityException繼承,如黑名單用戶(例如,如果用戶被列入黑名單例如,如果用戶經常像機器人一樣執行相同的操作(可能會要求通過驗證碼)等。

4

我想對於處理傳入的GWT調用,你使用一些Spring MVC控制器或一些servlet。它可以有以下邏輯

try{ 
    // decode payload from GWT call 
    com.google.gwt.user.server.rpc.RPC.decodeRequest(...) 
    // get spring bean responsible for actual business logic 
    Object bean = applicationContext.getBean(beanName); 
    // execute business logic and encode response 
    return RPC.invokeAndEncodeResponse(bean, ….) 
} catch (com.google.gwt.user.server.rpc.UnexpectedException ex) { 
    // send unexpected exception to client 
    return RPC.encodeResponseForFailure(..., new MyCustomUnexpectedException(), …) ; 
} 

解決方案這種情況下

HttpServletRequest request = getRequest() ; 
if (request.getRequestedSessionId() != null && !request.isRequestedSessionIdValid()) { 
    return RPC.encodeResponseForFailure(..., new MyCustomSessionExpiredException(), …) ; 
} else { 
    // first code snippet goes here 
} 

然後趕上定義會話的客戶端代碼過期例外。如果您不直接使用RPC,請提供GWT和Spring之間橋接實現的更多詳細信息。

您還需要強制GWT編譯器將MyCustomSessionExpiredException類型包括到序列化白名單中(以防止GWT安全策略停止向客戶端傳播異常的情況)。解決方案:包括MyCustomSessionExpiredException類型到每個同步接口的每個方法的簽名:

@RemoteServiceRelativePath("productRpcService.rpc") 
public interface ProductRpcService extends RemoteService { 
    List<Product> getAllProducts() throws ApplicationException; 
    void removeProduct(Product product) throws ApplicationException; 
} 

MyCustomSessionExpiredException extends ApplicationException 

然後顯示彈出在客戶端代碼:

public class ApplicationUncaughtExceptionHandler implements GWT.UncaughtExceptionHandler { 
    @Override   
    public void onUncaughtException(Throwable caught) { 
     if (caught instanceof MyCustomSessionExpiredException) { 
      Window.alert("Session expired"); 
     } 
    } 
} 

// Inside of EntryPoint.onModuleLoad method 
GWT.setUncaughtExceptionHandler(new ApplicationUncaughtExceptionHandler()); 
+0

非常感謝您分享您的知識。你的方法很好,但它將傳輸層與業務代表混合在一起,並使用內部的GWT API,這是不鼓勵的。請參閱我的答案中的演示,你可以在谷歌代碼託管中找到。謝謝。 –

相關問題