我有Spring MVC应用程序,其中安全性由Spring Security处理。
UI是使用GWT构建的,GWT使用RPC方法从服务器获取数据。
我需要在会话过期时处理UI的情况: 例如,RPC AsyncCallback可以获取SessionExpiredException类型的异常并弹出窗口,其中包含“您的会话已过期,请单击刷新链接”等消息。
有人处理过这样的问题吗?
感谢。
答案 0 :(得分: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());
答案 1 :(得分: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
步骤:
开发新的过滤器,首先拦截
在每个RPC方法服务中声明SessionExpiredException
,为简单起见,可以继承RuntimeException
(无需在实施者中遵循这一点)
开发父通用AsyncCallback
处理程序
使用http://code.google.com/p/gspring/解决方案来处理所有传入的RCP请求。
第二个更简单:在UI端返回401 HTTP错误和句柄(GWT本机常规异常包含HTTP状态编号)。示例:http://code.google.com/p/gspring/source/browse/#svn%2Ftrunk%2Fsample%2Fsession-expired-401
第二种方法最简单,不需要在服务方法契约中声明Exception。但是,遵循第一种方法可以给你一些灵活性:它可以包含一些额外的信息,如上次登录时间(对于SessionExpiredException
)等。另外,第二种方法可以引入新的例外,这些例外是从SecurityException
继承的,如黑名单用户(例如,如果用户在会话期间被列入黑名单),或者例如,如果用户经常执行相同的操作,例如机器人(可能会要求传递验证码)等。