web-dev-qa-db-ja.com

jsessionidは、jstl <c:url ..>タグによって生成されるすべてのURLで発生します

いくつかの奇妙なバグがあります。ブラウザで初めてページを開いたとき、すべての参照にjsessionidパラメータ(<a href="/articles?name=art&jsessionid=5as45df4as5df"..>など)があります。

F5キーを押すか、他の方法でページを更新すると、すべてのものが消え、ブラウザーを閉じるまですべてが正常に機能します(すべてのタブも閉じる必要があります)。もう一度開くと、この奇妙なjsessionidパラメータが表示されます。

すべてのURLを作成するためにjstl <c:url..>タグを使用します。

Cookieが無効になっている場合、jsessionidはCookieの代わりになることを少し前に読んだことがありますが、Cookieは有効になっていて、実際にはCookieを使用していません。

30
Roman

これはバグではなく、仕様によるものです。新しいセッションが作成されると、サーバーはクライアントがCookieをサポートしているかどうかを確認できないため、URLにjsessionidだけでなくCookieも生成します。クライアントが2回目に戻ってCookieを提示すると、サーバーはjsessionidが不要であることを認識し、残りのセッションでそれをドロップします。クライアントがCookieなしで戻ってきた場合、サーバーはjsessionidの書き換えを引き続き使用する必要があります。

明示的にCookieを使用することはできませんが、暗黙的にセッションがあり、コンテナはそのセッションを追跡する必要があります。

39
skaffman

skaffman's answer で説明されているように、はバグではありません。その予想される動作

あなたの質問では、jsessionidがパラメータとして追加されていますが、そうではありません。
使用
_<c:url value="/"/>_
は次のようなものを生成します:_/some/;jsessionid=E85FAC04E331FFCA55549B10B7C7A4FA_。
使用する
_<link href="<c:url value="/"/>stylesheets/style.css" rel="stylesheet" type="text/css"/>_
生成されます
_/some/;jsessionid=E85FAC04E331FFCA55549B10B7C7A4FAstylesheets/style.css_
、サーバーは利用可能なリソースを見つけることができません。

私が見つけた最善の回避策は、_${pageContext.request.contextPath}_の代わりに_<c:url value="/"/>_を使用することです-_。したがって、前の例では、
_<link href="${pageContext.request.contextPath}/stylesheets/style.css" rel="stylesheet" type="text/css"/>_
生成されます
_/some/stylesheets/style.css_。

このソリューションはコンテナに依存しません(Tomcatのようなサーブレット仕様v3準拠のコンテナはソリューションではありません)。応答URLのフィルタリングはハックのように感じられるため、デフォルトの動作を変更する必要があります。しかし、すべてはあなたが必要とし、達成したいことに依存しています。

26
despot

Tomcat 7または任意のサーブレット仕様v3準拠サーバーでは、アプリケーションのweb.xmlに以下を追加することにより、URLのjsessionidを無効にすることができます

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

Filterのフレーバーの厄介な回避策を次に示します。これにより、クライアントがCookieをサポートしているときはいつでも、URLにjsessionidが表示されなくなります。

@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);
}

/*またはセッション管理が必要なURLパターンにマッピングします。

5
BalusC

すべてのページが使用する共通のラッパーページがある場合(私にとってはcommon.incでした)、session="false"<%@ pageに追加して、セッションIDを削除できます。

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 }" />

または、c:urlの値を変数に設定し、c:out escapeXml="false"を使用して変数を出力すると、セッションIDが削除されます。

例:

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

または、これをApache構成に追加して、セッションIDを切り捨てることもできます。

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

残念ながら、これを回避する唯一の方法は、jsessionidパラメータを取り除くフィルタをアプリケーションに追加することです。公開Webサイトを作成していて、検索エンジンでページのインデックスを作成したい場合は、特に煩わしいです。

Tomcat(もしそれがあなたが使っているものなら)がこれをあなたのURLに追加しないように設定できるとは信じていません。他のサーバーについては言えません。

ただし、フィルターを作成してからセッション管理が必要で、ユーザーがCookieをオフにしている場合は、問題が発生することに注意してください。

0

回避策の1つは、<c:url>を使用するのではなく、${request.contextPath}/pathを使用することです。

0
Bozho