我有Spring安全性由Spring Security處理的Spring MVC應用程序。如何在Spring MVC-Spring安全應用程序中處理GWT RPC調用中的會話過期異常
UI是使用GWT構建的,它使用RPC方法從服務器獲取數據。
我需要在UI上處理會話過期的情況: 例如,RPC AsyncCallback可以獲取SessionExpiredException類型的異常,並彈出窗口,顯示消息如「您的會話已過期,請單擊刷新鏈接」等。
有人處理這樣的問題嗎?
謝謝。
我有Spring安全性由Spring Security處理的Spring MVC應用程序。如何在Spring MVC-Spring安全應用程序中處理GWT RPC調用中的會話過期異常
UI是使用GWT構建的,它使用RPC方法從服務器獲取數據。
我需要在UI上處理會話過期的情況: 例如,RPC AsyncCallback可以獲取SessionExpiredException類型的異常,並彈出窗口,顯示消息如「您的會話已過期,請單擊刷新鏈接」等。
有人處理這樣的問題嗎?
謝謝。
我研究了一下,這裏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
步驟:
開發新的過濾器,其截取第一
在其中可以繼承RuntimeException
爲了簡單(不需要遵循此在實施者)每個RPC方法服務聲明SessionExpiredException
開發父級通用AsyncCallback
處理程序
使用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
繼承,如黑名單用戶(例如,如果用戶被列入黑名單例如,如果用戶經常像機器人一樣執行相同的操作(可能會要求通過驗證碼)等。
我想對於處理傳入的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());
非常感謝您分享您的知識。你的方法很好,但它將傳輸層與業務代表混合在一起,並使用內部的GWT API,這是不鼓勵的。請參閱我的答案中的演示,你可以在谷歌代碼託管中找到。謝謝。 –