【问题标题】:Spring Security exclude URL in timeoutSpring Security 在超时时排除 URL
【发布时间】:2020-12-27 13:14:51
【问题描述】:

在 Spring Security 中,如何从重置会话超时中排除一个特定的 URL?总体应用程序会话超时 (server.servlet.session.timeout) 为 15 分钟。我们有一个来自网页的 ajax 调用,每 1 分钟调用一次。此调用需要保护,但不应影响会话时间。

我们尝试添加一个扩展 ConcurrentSessionFilter 的过滤器。此外,还有一个扩展 SessionManagementFilter 的过滤器。添加 ignoring() 也会跳过身份验证。没有任何帮助。在 Spring Security 中可以实现这个要求吗?有什么建议吗?

【问题讨论】:

  • 如果您不想延长会话,请不要发送会话cookie。但是,这意味着您无法使用现有会话并且您还没有登录。你在您的 AJAX 调用中,除了身份验证之外还需要会话吗?
  • 谢谢@dur。是的,我们只需要对这个 URL 进行身份验证的会话。
  • 那么你可以不使用这个 URL 的会话并使用 HTTP basic 进行身份验证。
  • 谢谢@dur。我们需要用户通过登录来验证自己。一旦他登录,我们就会定期进行 ajax 调用。只有这个调用不应该延长超时。请澄清您对此流程的基本身份验证的观点。
  • 如果你使用 HTTP basic 而不是表单登录,浏览器将存储用户名和密码,并在每次请求时发送。

标签: spring spring-mvc spring-security


【解决方案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 && 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);
    }

}

【讨论】:

    猜你喜欢
    • 2016-03-16
    • 2014-03-14
    • 2018-09-27
    • 2016-08-03
    • 2022-10-19
    • 2014-10-18
    • 2016-07-17
    • 2014-05-11
    • 1970-01-01
    相关资源
    最近更新 更多