Spring Security исключает URL-адрес во время ожидания

#spring #spring-mvc #spring-security

#spring #spring-mvc #spring-безопасность

Вопрос:

В Spring Security, как исключить один конкретный URL из сброса тайм-аута сеанса? Общий тайм-аут сеанса приложения (server.servlet.session.timeout) составляет 15 минут. У нас есть вызов ajax с веб-страницы, который будет вызываться каждые 1 минуту. Этот вызов должен быть защищен, но не должен влиять на время сеанса.

Мы попытались добавить фильтр, расширяющий ConcurrentSessionFilter. Кроме того, фильтр, расширяющий SessionManagementFilter. Добавление ignoring() также пропускает аутентификацию. Ничего не помогло. Может ли это требование быть выполнено в Spring Security? Есть предложения?

Комментарии:

1. Если вы не хотите продлевать сеанс, не отправляйте файл cookie сеанса. Однако это означает, что вы не можете использовать существующий сеанс, а также вы не вошли в систему. Вам нужен сеанс не только для аутентификации в вашем вызове AJAX?

2. Спасибо @dur . Да, нам нужен сеанс только для аутентификации по этому URL.

3. Тогда вы могли бы не использовать сеанс для этого URL-адреса и аутентифицировать с помощью HTTP basic.

4. Спасибо @dur . Нам нужно, чтобы пользователь аутентифицировался через логин. Как только он входит в систему, у нас возникает периодический вызов ajax. Только этот вызов не должен продлевать тайм-аут. Пожалуйста, разъясните свою точку зрения относительно базовой аутентификации для этого потока.

5. Если вы используете HTTP basic вместо формы входа, браузер сохранит имя пользователя и пароль и будет отправлять их с каждым запросом.

Ответ №1:

Вот как я с этим справился. Просто поделитесь, это может кому-то помочь. Пожалуйста, поделитесь любыми лучшими способами.

Фильтр Spring Security добавляется последним в цепочке.

 http.addFilterAfter(new SessionInvalidationFilter(timeOutInMinutes), SwitchUserFilter.class);
  

Он отслеживает lastUpdatedTime, который обновляется для всех вызовов, за исключением тех URL-адресов, которые необходимо игнорировать. В случае, если разность времени больше настроенного тайм-аута, сеанс становится недействительным.

 public class SessionInvalidationFilter extends GenericFilterBean {

    private static final String LASTUPDATEDDATETIME = "LASTUPDATEDDATETIME";

    private static final List<String> ignoredURLs = Arrays.asList("/Notifications/number"); // this is the AJAX URL

    private int timeOutInMinutes = 15;

    public SessionInvalidationFilter(int timeOutInMinutes) {
        this.timeOutInMinutes = timeOutInMinutes;
    }

    @Override
    /**
     * LASTUPDATEDDATETIME is updated for all calls except the ignoredURLs.
     * Session invalidation happens only during the ignoredURLs calls.
     */
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;

        HttpSession session = request.getSession(false);
        try {
            if (session != null amp;amp; request.getRequestURI() != null) {
                if (ignoredURLs.contains(request.getRequestURI())) {
                    Object lastUpdatedDateTimeObject = session.getAttribute(LASTUPDATEDDATETIME);
                    if (lastUpdatedDateTimeObject != null) {
                        LocalDateTime lastUpdatedDateTime = (LocalDateTime) lastUpdatedDateTimeObject;
                        long timeInMinutes = ChronoUnit.MINUTES.between(lastUpdatedDateTime, LocalDateTime.now());
                        if (timeInMinutes >= timeOutInMinutes) {
                            log.info("Timing out sessionID:{}", session.getId());
                            session.invalidate();
                            SecurityContextHolder.clearContext();
                        }
                    }
                } else {
                    session.setAttribute(LASTUPDATEDDATETIME, LocalDateTime.now());
                }
            }
        } catch (Exception e) {
            log.error("Exception in SessionInvalidationFilter", e);
        }

        chain.doFilter(request, response);
    }

}