Как обрабатывать исключение истекшего сеанса в Spring MVC-Spring Security app для вызовов GWT RPC
У меня есть приложение Spring MVC, где безопасность обрабатывается Spring Security.
Пользовательский интерфейс построен с использованием GWT, который получает данные от сервера с использованием подхода RPC.
Мне нужно обработать на UI ситуацию, когда сессия истекла: Например, RPC AsyncCallback может получить тип исключения SessionExpiredException и всплывающее окно с сообщением типа "ваш сеанс истек, пожалуйста, нажмите ссылку Обновить" или что-то еще.
Имел ли кто-нибудь дело с такими проблема?
Спасибо.
2 ответа:
Я предполагаю, что для обработки входящего вызова GWT вы используете какой-то контроллер Spring MVC или какой-то сервлет. Он может иметь следующую логику
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%253Dclosed.
Используйте
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.
второй , который намного проще: возвращает ошибку HTTP 401 и дескриптор в стороне пользовательского интерфейса (GWT native general exception содержит номер состояния HTTP). Пример: http://code.google.com/p/gspring/source/browse/#svn%2Ftrunk%2Fsample%2Fsession-expired-401
Второй подход является самым простым и не требует объявления исключения в методах обслуживания. контракт. Однако следование первому подходу может дать вам некоторую гибкость: он может содержать некоторую дополнительную информацию, такую как время последнего входа (для
SessionExpiredException
) и т. д. Кроме того, второй подход может ввести новые исключения, которые наследуются отSecurityException
, например, если пользователь был занесен в черный список во время сеанса, или, например, если пользователь делает те же действия очень часто, как робот (его можно попросить передать капчу) и т. д.