2010年3月24日水曜日

jsessionidはURLリライトとCookieどっちが優先されるか

HttpServletRequest#getRequestSessionId()でURLに付加したjsessionidとCookieにセットしたjsessionidのどちらが取得されるのかという問題だが、sessionトラッキングのサーブレット仕様から考えてCookieが優先されるだろう(セキュリティ的にも)。


引用 Java Servlet 2.5 Maintenance Release 2 (抜粋)
==============================================

SRV.7.1.1 Cookies
Session tracking through HTTP cookies is the most used session tracking
mechanism and is required to be supported by all servlet containers.
The container sends a cookie to the client. The client will then return the
cookie on each subsequent request to the server, unambiguously associating the
request with a session. The name of the session tracking cookie must be
JSESSIONID.


SRV.7.1.3 URL Rewriting
URL rewriting is the lowest common denominator of session tracking. When a
client will not accept a cookie, URL rewriting may be used by the server as the basis
for session tracking. URL rewriting involves adding data, a session ID, to the URL
path that is interpreted by the container to associate the request with a session.
The session ID must be encoded as a path parameter in the URL string. The
name of the parameter must be jsessionid. Here is an example of a URL
containing encoded path information:
==============================================



でも一応試してみた。
javascriptのonloadで、actionURLにCookieに設定されているものとは異なるjsessionidを付加するコードを追加して、その画面のリクエスト時にサーバのHttpServletRequest#getRequestSessionId()でCookieとURLパラメータのどちらが取得されるか。


結果
 Tomcat6.0実装 Cookie
 Seaser2(2.4.25) 実装 Cookie
 Weblogic9.2実装 Cookie


まぁ予想通りの結果ですね。
ちなみにwebsphereは試していませんが、下記サイトにCookieが優先されると書いてあります。
http://www.cresc.co.jp/tech/java/Servlet_Tutorial/Lesson_53.htm











2010年3月20日土曜日

Tomcatを自己証明書でSSLにする方法

Tomcat6.0でWebアプリ開発をしていて、手軽にSSLを試せる方法です。


keystoreファイルを作成
  keytool -genkey -alias tomcat -keyalg RSA
  C:/Documents and Settings/ユーザ名/.keystoreに作成されたが、環境によって違うかも。


server.xmlのSSL設定のコメントアウトをはずす。


keystorePass、keystoreFile属性を追加。
・keystorePass属性にはkeystoreファイル作成時に指定したパスワード

・keystoreFile属性にはkeystoreファイルのパ
例)
   <Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"   

               maxThreads="150" scheme="https" secure="true"
               clientAuth="false" sslProtocol="TLS"
               keystorePass="password" keystoreFile="C:/Program Files/Apache Software Foundation/Tomcat 6.0/conf/.keystore" />

Tomcatを再起動してSSLポート(8443)でアクセスでOK。



comodoとかで無償版SSLでちゃんとした証明書とることもできます。
http://jp.comodo.com/ssl-certificate-products/free-ssl-certificate.html


ApacheとTomcatを連携している場合はApacheでSSL設定を行います。
http://www.thinkit.co.jp/free/article/0706/3/7/





2010年3月18日木曜日

初回アクセス時のjsessionidを非表示にする

ブラウザを立ち上げて最初にアクセスしたときにjsessionidが付加されてしまう。


ソースを追ってみると、初回はHttpServletRequest#isRequestedSessionIdFromCookie() がfalseを返してHttpServlet#encodeURL()でjsessionidを付加してました。
原因は初回アクセスはcookieが有効かどうかわからないからですね。


Servlet仕様で、セッションIDの格納先にCookieが使用できないクライアントを想定してURLへセッションIDを文字列付加しての送信もサポートすることを推奨してるから、だいたいどのフレームワークも同じ実装だと思います(いわゆるURLリライティング)。とりあえず、StrutsとTeedaはそうでした。
回避方法は、最初にアクセスするページの前にダミーページを用意してリダイレクトを行うことでcookie有効判定に通せばよさそうですね。


ひがさんのブログに書いてありました。
http://d.hatena.ne.jp/higayasuo/20080724/1216889790


Teedaでは、ダミーのhtmlとPageクラスを用意して、PageクラスのprerenderでHttpServletResponse#sendRedirect()を呼び出すことでうまくいきました!


cookieが無効のクライアントをケアしないのであれば、Webサーバの設定等でにげれそうですね。
weblogicなら、weblogic.xmlのurl-rewriting-enabledをfalseに設定するとか、Apacheのmod_rewriteを使用するとか。
あとは、いけてないけど判定ロジックを部分を拡張するとかもありますね。
TeedaだとServletExternalContextImpl #encodeActionURL()を拡張すればよさそう。


ちなみにSSLにすれば、HTTPのボディだけじゃなくてヘッダも暗号化されるんだよね?
という疑問が沸いたので調べてみた。
じゃないとリファラとかでURLパラメータの方が危険性は高いと言っても、
ネットワークには平分で流れちゃうし。


SSLはTCP階層の暗号化なので、HTTPのヘッダもボディも暗号化されるようです。
GETパラメータももちろん暗号化されますね。
http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=1991&forum=12























2010年3月17日水曜日

SSLとjavascript(IEの警告ダイアログ対応)

作成してるWebサイトをSSLにしたとたん、以下のようなメッセージの警告ダイアログがやたら表示されたので、原因と対処方法まとめ。

「このページにはセキュリティで保護されている項目と保護されていない項目が含まれています。保護されていない項目を表示しますか?」


基本的には、httpのリクエストとhttpsのリクエストが混ざっているページで表示されるダイアログのはずなので、パケットモニタしてリクエストを見てみたが、「http:」で始まるリクエストは飛んでない。
ググってみると、どうもiframeのsrc属性が空の場合にも発生するようだ。 http://support.microsoft.com/kb/261188/ja

なんてこった、画面部品としていくつかsrc属性なしでiframeを使用しているわ。

IE6、7、8で試したが出るのはIE6のみ。
基本的にはインターネットオプションの「保護つき/保護なしサイト間を移動する場合に警告する」のチェックをはずせば問題ないのだけど、IE6のデフォルトはチェックあり。。

対応方法は、ダミーのhtml(空ファイル)を用意して、src属性に指定するだけです。
.htmlに対してservletが動作してしまう設定のときはdummy.htmとか適当に拡張子を変更すればOK.

よし、解決! と思っていたら今度は別Windowを使ってところで
以下の警告ダイアログが。。
「セキュリティで保護されたページに接続します」
セキュリティーで保護されていないページに移動しようとしています」

window.openのURLパラメータを指定していないとこが原因の模様。
window.openでURLパラメータに空を指定していると、SSL切断→SSL接続という
動きになりSSL開始と終了の警告ダイアログが表示されるみたい。

これも対応方法は、iframeと同様でダミーHTMLを指定することで解決。


2010/07/17追記
ちなみにiframeの方はsrc="javascript:false"みたいな書き方でもいけるが、
透明でレイヤーにしてるiframeとかの場合、falseって文字が出ちゃいますw
文字が出ちゃうとか関係ない用途なら こっちの方が リクエスト発生しない
のでパフォーマンス的によいね。
window.openの方はjavascript:falseは効果ありませんでした。