Как обрабатывать исключение истекшего сеанса в Spring MVC-Spring Security app для вызовов GWT RPC


У меня есть приложение Spring MVC, где безопасность обрабатывается Spring Security.

Пользовательский интерфейс построен с использованием GWT, который получает данные от сервера с использованием подхода RPC.

Мне нужно обработать на UI ситуацию, когда сессия истекла: Например, RPC AsyncCallback может получить тип исключения SessionExpiredException и всплывающее окно с сообщением типа "ваш сеанс истек, пожалуйста, нажмите ссылку Обновить" или что-то еще.

Имел ли кто-нибудь дело с такими проблема?

Спасибо.

2 3

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

Шаги:

  1. Разработайте новый фильтр, который сначала перехватывает

  2. Объявляйте SessionExpiredException в каждом сервисе метода RPC, который мог бы наследовать RuntimeException для простоты (нет необходимости следовать этому в реализаторах)

  3. Разработать Родительский универсальный AsyncCallback обработчик

  4. Использование 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, например, если пользователь был занесен в черный список во время сеанса, или, например, если пользователь делает те же действия очень часто, как робот (его можно попросить передать капчу) и т. д.