You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何配置Payara禁止为根路径/颁发JSESSIONID 防范会话固定漏洞

Payara Server 重复JSESSIONID问题修复方案

根因说明

Payara Server 5.2021.10 基于GlassFish内核实现,默认会在用户首次访问动态资源时自动创建会话、下发路径为/的JSESSIONID,当应用部署在/my-app上下文路径、登录完成后容器又会下发路径匹配应用上下文的JSESSIONID,两个Cookie同时留存不仅会导致会话匹配混乱,还确实存在会话固定漏洞风险。可通过以下两类方案实现登录前不返回JSESSIONID:

方案1:web.xml 容器配置(无代码侵入,优先推荐)

直接在应用WEB-INF/web.xml中添加如下配置,从容器层面关闭提前创建会话的逻辑、统一Cookie规则:

<session-config>
    <!-- 仅当代码显式调用会话创建逻辑时才生成JSESSIONID,禁止请求自动触发会话创建 -->
    <session-properties>
        <property name="enableSessionCreationRequirement" value="true"/>
    </session-properties>
    <cookie-config>
        <!-- 统一所有会话Cookie的作用路径为应用上下文,彻底杜绝根路径/的冗余JSESSIONID -->
        <path>/my-app</path>
        <http-only>true</http-only>
        <secure>true</secure>
        <!-- 登录成功后自动更换Session ID,从容器层面阻断会话固定漏洞 -->
        <change-session-id-on-login>true</change-session-id-on-login>
    </cookie-config>
    <!-- 会话超时时间根据业务需求配置即可 -->
    <session-timeout>30</session-timeout>
</session-config>

配置完成后重启应用,未触发显式会话创建的公开请求(比如登录页访问、登录参数校验阶段)都不会返回JSESSIONID。

方案2:Java代码侧控制(适配无法调整容器配置的场景)

如果无法修改web.xml全局配置,可通过代码逻辑从请求入口拦截控制:

  • 所有公开访问的资源(登录页、静态资源、登录校验接口未通过前),禁止调用request.getSession()、request.getSession(true)方法,这两个方法会强制触发新会话创建;如果需要判断用户是否已登录,仅调用request.getSession(false),该方法在无有效会话时返回null,不会生成新会话。
  • 如果项目使用JSP作为视图层,需要在所有公开访问的JSP页面顶部添加<%@ page session="false" %>指令,关闭JSP渲染时自动创建会话的默认逻辑;如果使用JSF,需要在对应视图配置中关闭预创建会话的开关。
  • 新增全局过滤器,在请求完成后清理未登录场景下被容器自动添加的冗余JSESSIONID,核心实现如下:
@WebFilter(filterName = "sessionPreventFilter", urlPatterns = "/*")
public class SessionPreventFilter implements Filter {
    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;
        chain.doFilter(req, resp);
        // 未登录判断逻辑根据自身系统鉴权规则调整,示例为容器内置身份校验的判断方式
        if (request.getUserPrincipal() == null) {
            Collection<String> cookieHeaders = response.getHeaders("Set-Cookie");
            // 清理所有路径为/的JSESSIONID下发逻辑
            for (String cookieHeader : cookieHeaders) {
                if (cookieHeader.startsWith("JSESSIONID") && cookieHeader.contains("Path=/;")) {
                    response.setHeader("Set-Cookie", cookieHeader.replaceAll("JSESSIONID=[^;]*;", "JSESSIONID=deleted;Max-Age=0;"));
                }
            }
        }
    }
}
  • 登录校验通过后,再显式调用request.getSession()创建用户会话,同时调用Servlet 3.1+提供的request.changeSessionId()方法更换会话标识,彻底规避会话固定风险。

注意:如果应用引入了Spring Security、Shiro等安全框架,需要同步检查框架配置中是否存在提前创建会话的逻辑,将公开路径的会话创建策略调整为never,避免框架层提前触发JSESSIONID下发。

内容的提问来源于stack exchange,提问作者jhansen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 23:57:25