我有 Spring MVC 应用程序,其中安全性由 Spring Security 处理。
UI 是使用 GWT 构建的,它使用 RPC 方法从服务器获取数据。
我需要在 UI 上处理会话过期的情况:例如 RPC AsyncCallback 可以获得 SessionExpiredException 类型的异常并弹出窗口,其中包含“您的会话已过期,请单击刷新链接”之类的消息。
有人处理过这样的问题吗?
谢谢。
我有 Spring MVC 应用程序,其中安全性由 Spring Security 处理。
UI 是使用 GWT 构建的,它使用 RPC 方法从服务器获取数据。
我需要在 UI 上处理会话过期的情况:例如 RPC AsyncCallback 可以获得 SessionExpiredException 类型的异常并弹出窗口,其中包含“您的会话已过期,请单击刷新链接”之类的消息。
有人处理过这样的问题吗?
谢谢。
我想为了处理传入的 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());
我研究了一下并在此处上传了解决方案http://code.google.com/p/gspring/source/browse/#svn%2Ftrunk%2Fsample%2Fsession-expired%253Fstate%253Dclose。
签出后用于mvn jetty:run-war
查看演示并转到rpc-security-sample/index.htm
有两种方法可以解决它。
第一个是传递 GWT 的委托代理,它在方法调用期间RemoteServlet
抛出。SessionExpiredException
这需要Exception
在每个 RPC 服务方法中声明。示例:http ://code.google.com/p/gspring/source/browse/#svn%2Ftrunk%2Fsample%2Fsession-expired%253Fstate%253Dclosed
脚步:
开发先拦截的新过滤器
SessionExpiredException
为简单起见,在每个可以继承的 RPC 方法服务中声明RuntimeException
(实现者无需遵循此)
开发父通用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
第二种方法最简单,不需要在服务方法合同中声明异常。但是,遵循第一种方法可以为您提供一些灵活性:它可以包含一些附加信息,例如上次登录时间 (for SessionExpiredException
) 等。第二种方法还可以引入新的异常,这些异常是从SecurityException
类似黑名单的用户继承的(例如,如果用户在他的会话)或者例如,如果用户像机器人一样经常执行相同的操作(可能会要求它传递验证码)等。