如何在Spring MVC Spring Security应用程序中为GWT RPC调用处理会话过期异常



我有一个Spring MVC应用程序,其中安全性由Spring security处理。

UI是使用GWT构建的,GWT使用RPC方法从服务器获取数据。

我需要在UI上处理会话过期时的情况:例如,RPC AsyncCallback可以获取SessionExpiredException类型的异常,并弹出窗口,显示类似"您的会话已过期,请单击刷新链接"之类的消息。

有人处理过这样的问题吗?

谢谢。

我想,为了处理传入的GWT调用,您可以使用一些SpringMVC控制器或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());

我研究了一下,并将解决方案上传到了这里http://code.google.com/p/gspring/source/browse/#svn%2Ftrunk%2Fsample%2Fsession-已过期%253F状态%253D已关闭。

检查后使用mvn jetty:run-war查看演示并转到rpc-security-sample/index.htm

有两种方法可以解决它

第一个是传递GWTRemoteServlet的委托代理,它在方法调用期间抛出SessionExpiredException。这需要在每个RPC服务方法中声明Exception。示例:http://code.google.com/p/gspring/source/browse/#svn%2Ftrunk%2Fsample%2Fsession-已过期%253F状态%253D已关闭

步骤:

  1. 开发拦截第一个的新过滤器

  2. 在每个RPC方法服务中声明SessionExpiredException,为了简单起见,可以继承RuntimeException(在实现者中无需遵循此步骤)

  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-过期-401

第二种方法是最简单的,不需要在服务方法契约中声明Exception。然而,遵循第一种方法可以给您一些灵活性:它可以包含一些额外的信息,如上次登录时间(对于SessionExpiredException)等。此外,第二种方法可以引入从SecurityException继承的新异常,如列入黑名单的用户(例如,如果用户在会话期间被列入黑名单),或者如果用户像机器人一样经常做同样的动作(可以要求它通过captcha)等。

最新更新