HTTP 会话:如何配置不更改会话过期时间的 URL?
HTTP Session: how to configure URLs that not change the session expiration?
我的应用程序轮询每 5 分钟执行一次的 HTTP 请求。
我想将这些 URL 配置为不更改会话到期时间。
否则我的会话将永远不会过期(我不想要它)。
在 web.xml 和 HttpSession 文档中找不到它。
怎么可能呢?
已添加
非常重要的说明:应该对请求进行身份验证。
这意味着请求应该附加到已经通过身份验证的 JsessionID。
澄清(添加 2)
我不希望无论用户是否保持活动状态,会话都会过期。我希望会话将在用户不活动时过期,并且如果用户在 UI 上工作则不会过期。我希望会话将在用户不活动时过期,尽管每 5 分钟出现一次轮询请求
在您的情况下,您需要一个 Session 管理方案,无论用户是否保持活动状态,该方案都将在 N 分钟后过期。这样您就不需要绕过任何身份验证或默认 cookie。
您可以使用建议的两种方法来实现它here。
- 一个计划作业,它在登录
后 N 分钟后使 session 无效
- 一种 Header 和基于过滤器的方法来动态决定 session 到期。
有很多方法可以做到这一点。其中之一是使用 javascript 例如 JQuery 。主要思想是不管脚本是否在轮询服务器,如果用户在应用程序上没有 activity 在合理的时间内(例如按键、鼠标移动等),则需要考虑用户不存在,javascript 需要为您的应用程序调用注销 url。请参考提供的URL,实际上很好地解释了这个概念。
标准 Servlet 不支持此功能 API。
您最好的选择是创建一个全局 servlet 过滤器(使用 @WebFilter("/*")
),每次当特定 URL 访问服务器时减少 HttpSession#setMaxInactiveInterval()
,并将其放回其他 URL 的默认值。它只需要一点基础数学。
实现的相关部分如下所示:
private static final int DEFAULT_EXPIRE_TIME_IN_SECONDS = 1800;
private static final String SKIP_EXPIRE_TIME_ON_URI = "/somePollServlet";
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpSession session = request.getSession();
if (request.getRequestURI().equals(request.getContextPath() + SKIP_EXPIRE_TIME_ON_URI)) {
long lastAccessedTime = session.getLastAccessedTime();
long currentTime = System.currentTimeMillis();
int newExpireTime = DEFAULT_EXPIRE_TIME_IN_SECONDS - (int) ((currentTime - lastAccessedTime) / 1000);
session.setMaxInactiveInterval(newExpireTime);
}
else {
session.setMaxInactiveInterval(DEFAULT_EXPIRE_TIME);
}
chain.doFilter(req, res);
}
这是@BalusC 的更新答案。他的解决方案并不完全适合我。试试这个解决方案。
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
int expireTimeInSeconds = 60;
String skippableUrl = "/url";
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpSession session = request.getSession();
int maxInactiveInterval = session.getMaxInactiveInterval();
if (request.getRequestURI().equals(request.getContextPath() + skippableUrl )) {
long lastAccessedTime = session.getLastAccessedTime();
long currentTime = System.currentTimeMillis();
int newMaxInactiveInterval = maxInactiveInterval - (int) ((currentTime - lastAccessedTime) / 1000);
if (newMaxInactiveInterval <= 0 || maxInactiveInterval > expireTimeInSeconds) {
session.invalidate();
} else {
session.setMaxInactiveInterval(newMaxInactiveInterval);
}
} else {
session.setMaxInactiveInterval(expireTimeInSeconds);
}
filterChain.doFilter(servletRequest, servletResponse);
}
我的应用程序轮询每 5 分钟执行一次的 HTTP 请求。
我想将这些 URL 配置为不更改会话到期时间。 否则我的会话将永远不会过期(我不想要它)。 在 web.xml 和 HttpSession 文档中找不到它。
怎么可能呢?
已添加
非常重要的说明:应该对请求进行身份验证。 这意味着请求应该附加到已经通过身份验证的 JsessionID。
澄清(添加 2)
我不希望无论用户是否保持活动状态,会话都会过期。我希望会话将在用户不活动时过期,并且如果用户在 UI 上工作则不会过期。我希望会话将在用户不活动时过期,尽管每 5 分钟出现一次轮询请求
在您的情况下,您需要一个 Session 管理方案,无论用户是否保持活动状态,该方案都将在 N 分钟后过期。这样您就不需要绕过任何身份验证或默认 cookie。
您可以使用建议的两种方法来实现它here。
- 一个计划作业,它在登录 后 N 分钟后使 session 无效
- 一种 Header 和基于过滤器的方法来动态决定 session 到期。
有很多方法可以做到这一点。其中之一是使用 javascript 例如 JQuery 。主要思想是不管脚本是否在轮询服务器,如果用户在应用程序上没有 activity 在合理的时间内(例如按键、鼠标移动等),则需要考虑用户不存在,javascript 需要为您的应用程序调用注销 url。请参考提供的URL,实际上很好地解释了这个概念。
标准 Servlet 不支持此功能 API。
您最好的选择是创建一个全局 servlet 过滤器(使用 @WebFilter("/*")
),每次当特定 URL 访问服务器时减少 HttpSession#setMaxInactiveInterval()
,并将其放回其他 URL 的默认值。它只需要一点基础数学。
实现的相关部分如下所示:
private static final int DEFAULT_EXPIRE_TIME_IN_SECONDS = 1800;
private static final String SKIP_EXPIRE_TIME_ON_URI = "/somePollServlet";
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpSession session = request.getSession();
if (request.getRequestURI().equals(request.getContextPath() + SKIP_EXPIRE_TIME_ON_URI)) {
long lastAccessedTime = session.getLastAccessedTime();
long currentTime = System.currentTimeMillis();
int newExpireTime = DEFAULT_EXPIRE_TIME_IN_SECONDS - (int) ((currentTime - lastAccessedTime) / 1000);
session.setMaxInactiveInterval(newExpireTime);
}
else {
session.setMaxInactiveInterval(DEFAULT_EXPIRE_TIME);
}
chain.doFilter(req, res);
}
这是@BalusC 的更新答案。他的解决方案并不完全适合我。试试这个解决方案。
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
int expireTimeInSeconds = 60;
String skippableUrl = "/url";
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpSession session = request.getSession();
int maxInactiveInterval = session.getMaxInactiveInterval();
if (request.getRequestURI().equals(request.getContextPath() + skippableUrl )) {
long lastAccessedTime = session.getLastAccessedTime();
long currentTime = System.currentTimeMillis();
int newMaxInactiveInterval = maxInactiveInterval - (int) ((currentTime - lastAccessedTime) / 1000);
if (newMaxInactiveInterval <= 0 || maxInactiveInterval > expireTimeInSeconds) {
session.invalidate();
} else {
session.setMaxInactiveInterval(newMaxInactiveInterval);
}
} else {
session.setMaxInactiveInterval(expireTimeInSeconds);
}
filterChain.doFilter(servletRequest, servletResponse);
}