Tomcat / Java Web アプリで HttpOnly Cookie を構成するにはどうすればよいですか?
質問
Jeff のブログ投稿を読んだ後、 Cookie を保護する:HTTPのみ. 。Web アプリケーションに HttpOnly Cookie を実装したいと考えています。
Tomcat に http のみの Cookie をセッションに使用するように指示するにはどうすればよいですか?
解決
httpOnly は Tomcat 6.0.19 および Tomcat 5.5.28 以降でサポートされています。
を参照してください。 変更履歴 バグ 44382 のエントリ。
バグに対する最後のコメント 44382 「これは5.5.xに適用されており、5.5.28以降に含まれます。」ただし、5.5.28がリリースされているようには見えません。
httpOnly 機能は、次のすべての Web アプリに対して有効にできます。 conf/context.xml:
<Context useHttpOnly="true">
...
</Context>
私の解釈では、目的のコンテキストに設定することで、個々のコンテキストにも機能するということです。 コンテクスト エントリー conf/server.xml (上記と同じ方法で)。
他のヒント
アップデート:ここのjsessionidのものは、古い容器専用です。<tomcat 6.0.19または<tomcat 5.5.28またはhttponly jsessionid cookiesを構成オプションとしてサポートしていない別のコンテナを使用していない限り、JTの現在受け入れられている回答を使用してください。
アプリに Cookie を設定する場合は、次を使用します。
response.setHeader( "Set-Cookie", "name=value; HttpOnly");
ただし、多くの Web アプリでは、最も重要な Cookie はセッション ID であり、コンテナによって JSESSIONID Cookie として自動的に設定されます。
この Cookie のみを使用する場合は、途中で Cookie を再設定する ServletFilter を作成し、JSESSIONID を強制的に HttpOnly に設定できます。のページ http://keepitlocked.net/archive/2007/11/05/java-and-httponly.aspx http://alexsmolen.com/blog/?p=16 フィルターに以下を追加することを提案します。
if (response.containsHeader( "SET-COOKIE" )) {
String sessionid = request.getSession().getId();
response.setHeader( "SET-COOKIE", "JSESSIONID=" + sessionid
+ ";Path=/<whatever>; Secure; HttpOnly" );
}
ただし、これによりすべての Cookie が上書きされ、このフィルターにはここで指定した内容のみが設定されることに注意してください。
JSESSIONID Cookie に追加の Cookie を使用する場合は、このコードを拡張してフィルター内のすべての Cookie を設定する必要があります。これは、複数の Cookie の場合には優れた解決策ではありませんが、JSESSIONID のみのセットアップではおそらく受け入れられるクイックフィックスです。
コードは時間の経過とともに進化するため、このフィルターを忘れてコード内の別の場所に別の Cookie を設定しようとすると、厄介な隠れたバグが待ち構えていることに注意してください。もちろん固まりません。
ただし、これは本当にハックです。Tomcat を実際に使用し、コンパイルできる場合は、HttpOnly サポートを Tomcat にパッチするための Shabaz の優れた提案を参照してください。
httpsセッションの「;secure」Cookieフラグを上書きしないように注意してください。このフラグは、ブラウザが暗号化されていない http 接続を介して Cookie を送信することを防ぎ、基本的に正規のリクエストに対する https の使用を無意味にします。
private void rewriteCookieToHeader(HttpServletRequest request, HttpServletResponse response) {
if (response.containsHeader("SET-COOKIE")) {
String sessionid = request.getSession().getId();
String contextPath = request.getContextPath();
String secure = "";
if (request.isSecure()) {
secure = "; Secure";
}
response.setHeader("SET-COOKIE", "JSESSIONID=" + sessionid
+ "; Path=" + contextPath + "; HttpOnly" + secure);
}
}
セッション Cookie については、Tomcat ではまだサポートされていないようです。バグレポートを参照 HTTPOnly セッション Cookie パラメータのサポートを追加する必要がある. 。現時点では、多少複雑な回避策が見つかります ここ, 、これは基本的に Tomcat に手動でパッチを適用することになります。残念ながら、現時点ではそれを行う簡単な方法は見つかりません。
回避策を要約すると、5.5 をダウンロードする必要があります。 ソース, 次に、次の場所のソースを変更します。
org.apache.catalina.connector.Request.java
//this is what needs to be changed
//response.addCookieInternal(cookie);
//this is whats new
response.addCookieInternal(cookie, true);
}
org.apache.catalina.connectorResponse.addCookieInternal
public void addCookieInternal(final Cookie cookie) {
addCookieInternal(cookie, false);
}
public void addCookieInternal(final Cookie cookie, boolean HTTPOnly) {
if (isCommitted())
return;
final StringBuffer sb = new StringBuffer();
//web application code can receive a IllegalArgumentException
//from the appendCookieValue invokation
if (SecurityUtil.isPackageProtectionEnabled()) {
AccessController.doPrivileged(new PrivilegedAction() {
public Object run(){
ServerCookie.appendCookieValue
(sb, cookie.getVersion(), cookie.getName(),
cookie.getValue(), cookie.getPath(),
cookie.getDomain(), cookie.getComment(),
cookie.getMaxAge(), cookie.getSecure());
return null;
}
});
} else {
ServerCookie.appendCookieValue
(sb, cookie.getVersion(), cookie.getName(), cookie.getValue(),
cookie.getPath(), cookie.getDomain(), cookie.getComment(),
cookie.getMaxAge(), cookie.getSecure());
}
//of course, we really need to modify ServerCookie
//but this is the general idea
if (HTTPOnly) {
sb.append("; HttpOnly");
}
//if we reached here, no exception, cookie is valid
// the header name is Set-Cookie for both "old" and v.1 ( RFC2109 )
// RFC2965 is not supported by browsers and the Servlet spec
// asks for 2109.
addHeader("Set-Cookie", sb.toString());
cookies.add(cookie);
}
Web サーバーが Serlvet 3.0 仕様 (Tomcat 7.0+ など) をサポートしている場合は、以下を使用できます。 web.xml
として:
<session-config>
<cookie-config>
<http-only>true</http-only>
<secure>true</secure>
</cookie-config>
</session-config>
ドキュメントに記載されているように:
HTTPのみ:このWebアプリケーションによって作成されたCookieを追跡するセッションを追跡するセッションは、httponlyとしてマークされるかどうかを指定します
安全な:このWebアプリケーションによって作成されたCookieを追跡するセッションを追跡するセッションは、対応するセッションを開始したリクエストがHTTPSの代わりにPlain HTTPを使用している場合でも安全としてマークされるかどうかを指定します
を参照してください。 Java WebアプリケーションにhttponlyとセッションCookieを設定する方法
また、HttpOnly をオンにすると、jvm へのステートフル アクセスを必要とするアプレットが壊れることにも注意してください。
アプレットの http リクエストは jsessionid cookie を使用しないため、別の Tomcat に割り当てられる可能性があります。
Tomcat6 では、HTTP リスナー クラスから条件付きで有効にすることができます。
public void contextInitialized(ServletContextEvent event) {
if (Boolean.getBoolean("HTTP_ONLY_SESSION")) HttpOnlyConfig.enable(event);
}
このクラスを使用する
import java.lang.reflect.Field;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import org.apache.catalina.core.StandardContext;
public class HttpOnlyConfig
{
public static void enable(ServletContextEvent event)
{
ServletContext servletContext = event.getServletContext();
Field f;
try
{ // WARNING TOMCAT6 SPECIFIC!!
f = servletContext.getClass().getDeclaredField("context");
f.setAccessible(true);
org.apache.catalina.core.ApplicationContext ac = (org.apache.catalina.core.ApplicationContext) f.get(servletContext);
f = ac.getClass().getDeclaredField("context");
f.setAccessible(true);
org.apache.catalina.core.StandardContext sc = (StandardContext) f.get(ac);
sc.setUseHttpOnly(true);
}
catch (Exception e)
{
System.err.print("HttpOnlyConfig cant enable");
e.printStackTrace();
}
}
}
で見つけました オワスプ
<session-config>
<cookie-config>
<http-only>true</http-only>
</cookie-config>
</session-config>
これは「設定内の httponlycookies」セキュリティ問題も修正します