Pergunta

Eu tenho um bug estranho: quando abro a página pela primeira vez em algum navegador, todas as referências tem o parâmetro JSessionID (como <a href="/articles?name=art&jsessionid=5as45df4as5df"..>).

Quando pressiono a F5 ou atualizo a página de qualquer outra maneira, tudo o que é desaparecido e tudo funciona bem até eu fechar meu navegador (e todas as guias também devem ser fechadas). Quando abro novamente, vejo esse estranho parâmetro JSessionID.

Eu uso JSTL <c:url..> tag para criar todos os URLs.

Eu li há algum tempo que o JSessionID é uma alternativa aos cookies se os cookies estiverem desativados, mas os cookies estão ativados e eu realmente não uso cookies.

Foi útil?

Solução

Isso não é um bug, é por design. Quando uma nova sessão é criada, o servidor não tem certeza se o cliente suporta cookies ou não, e, portanto, gera um cookie e o JSessionID no URL. Quando o cliente volta pela segunda vez e apresenta o cookie, o servidor sabe que o JSessionID não é necessário e o retira pelo restante da sessão. Se o cliente voltar sem cookie, o servidor precisará continuar usando a reescrita do JSessionID.

Você não pode usar explicitamente cookies, mas tem uma sessão implicitamente e o contêiner precisa rastrear essa sessão.

Outras dicas

Conforme explicado Resposta de Skaffman, não é um bug. É um comportamento esperado.

Em sua pergunta, o JSessionID é anexado como um parâmetro, o que não é o caso.
Usando
<c:url value="/"/>
irá gerar algo como o seguinte: /some/;jsessionid=E85FAC04E331FFCA55549B10B7C7A4FA.
Então usando
<link href="<c:url value="/"/>stylesheets/style.css" rel="stylesheet" type="text/css"/>
irá gerar
/some/;jsessionid=E85FAC04E331FFCA55549B10B7C7A4FAstylesheets/style.css
, para que seu servidor não possa encontrar o recurso disponível.

A melhor solução alternativa que encontrei é usar ${pageContext.request.contextPath} ao invés de <c:url value="/"/>. Então, no exemplo anterior, você teria
<link href="${pageContext.request.contextPath}/stylesheets/style.css" rel="stylesheet" type="text/css"/>
isso vai gerar
/some/stylesheets/style.css.

Esta solução é Independente do contêiner (enquanto a especificação do servlet v3 contêiner compatível - como o tomcat - a solução não é). Filtrar o URL de resposta parece um hack, porque você precisa alterar um comportamento padrão. Mas tudo depende do que você precisa e deseja alcançar.

No Tomcat 7 ou em qualquer servidor de especificação de servlet v3, você pode desativar o JSessionID no URL adicionando seguidores ao web.xml do seu aplicativo

<session-config>
    <tracking-mode>COOKIE</tracking-mode>
</session-config>

Aqui está uma solução alternativa desagradável em sabor de um Filter Para que você nunca verá o JSessionID no URL sempre que o cliente suporta cookies.

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    HttpServletRequest req = (HttpServletRequest) request;
    HttpServletResponse res = (HttpServletResponse) response;
    HttpSession session = req.getSession();

    if (session.isNew()) {
        // New session? OK, redirect to encoded URL with jsessionid in it (and implicitly also set cookie).
        res.sendRedirect(res.encodeRedirectURL(req.getRequestURI()));
        return;
    } else if (session.getAttribute("verified") == null) {
        // Session has not been verified yet? OK, mark it verified so that we don't need to repeat this.
        session.setAttribute("verified", true);
        if (req.isRequestedSessionIdFromCookie()) {
            // Supports cookies? OK, redirect to unencoded URL to get rid of jsessionid in URL.
            res.sendRedirect(req.getRequestURI().split(";")[0]);
            return;
        }
    }

    chain.doFilter(request, response);
}

Mapeie -o /* ou qualquer padrão de URL que exija gerenciamento de sessões.

Se você tem uma página de wrapper comum que todas as páginas usam (para mim era comum.inc), você pode adicionar session="false" para o seu <%@ page Para remover o SessionID.

Exemplo common.inc

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" session="false" trimDirectiveWhitespaces="true" %>
<%@ taglib prefix="ab" tagdir="/WEB-INF/tags" %>

<c:set var="contextPath" scope="request" value="${ pageContext.request.contextPath }" />
<c:set var="assetPath" scope="request" value="/assets" />
<c:set var="debugEnabled" scope="request" value="${ applicationDebugProperties.debugEnabled }" />

Alternativamente .. Defina o valor de c:url para uma variável e uso c:out escapeXml="false" Para produzir a variável e isso removerá o SessionID.

Exemplo:

<c:url value=${url} var="image"/>
<c:out var=${image} escapeXml="false"/>

Como alternativa, você pode adicionar isso à sua configuração do Apache para truncar o SessionID.

ReWriteRule ^/(\w+);jsessionid=\w+$ /$1 [L,R=301]
ReWriteRule ^/(\w+\.go);jsessionid=\w+$ /$1 [L,R=301]

Infelizmente, a única maneira que encontrei em torno disso é adicionar um filtro ao seu aplicativo que retirará o parâmetro JSessionID. É particularmente irritante se você estiver criando um site público e deseja que os mecanismos de pesquisa indexem suas páginas.

Não acredito que o Tomcat (se é isso que você está usando) pode ser configurado para não adicionar isso ao seu URL. Eu não posso dizer para os outros servidores.

No entanto, observe que, se você criar o filtro e precisar de gerenciamento de sessão e o usuário tiver cookies desligados, você terá problemas.

Uma solução alternativa não é usar <c:url>, mas para usar ${request.contextPath}/path

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top