- PR -

jsessionidの自動付加について

1
投稿者投稿内容
demanotto
会議室デビュー日: 2004/07/29
投稿数: 4
投稿日時: 2004-07-29 20:36
榎本と申します。

使用環境
OS Red Hat Linux 7.3 2.96-113
tomcat jakarta-tomcat-4.1.24-LE-jdk14
JDK j2sdk-1_4_1_04-linux-i586

@IT > Insider.NET > .NET TIPS >
[ASP.NET]クッキーをサポートしないクライアントでセッション機能を利用するには?
http://www.atmarkit.co.jp/fdotnet/dotnettips/189aspckless/aspckless.html

の記事にあるようなことをtomcatを使用してできないでしょうか?
Cookieを使用しない設定はserver.xmlに記述することでできることはわかっています。
<Context cookies="false">
Kissinger
ぬし
会議室デビュー日: 2002/04/30
投稿数: 428
お住まい・勤務地: 愛知県
投稿日時: 2004-07-30 03:05
榎本さん、こんにちは。

私の場合、いちいち
javax.servlet.http.HttpServletResponse#encodeURL(java.lang.String url)
を使用しリライトています。
kito
ベテラン
会議室デビュー日: 2003/03/24
投稿数: 59
お住まい・勤務地: Osaka
投稿日時: 2004-07-30 04:08
削除

[ メッセージ編集済み 編集者: kito 編集日時 2004-07-30 05:14 ]
kito
ベテラン
会議室デビュー日: 2003/03/24
投稿数: 59
お住まい・勤務地: Osaka
投稿日時: 2004-07-30 05:17
引用:

[ASP.NET]クッキーをサポートしないクライアントでセッション機能を利用するには?
http://www.atmarkit.co.jp/fdotnet/dotnettips/189aspckless/aspckless.html

の記事にあるようなことをtomcatを使用してできないでしょうか?



JSP/ServletはHTML文書を単なるテキストとして扱うので、こういう場面では不利ですね。
(JSF等では解決策があるかも?)

Filterを使って、文書中のリンクすべてにHttpResponse#encodeURL(String)を適用する
ことで、ほぼお望みの動作になると思います。
実際には、すべてのURLにSessionIDを付加するのはセキュリティ上まずいので、
encodeURL()の前に、URLのチェック(同一サーバーであるかどうか、同一webappであるかどうか等)
をした方が良いです。

コードは下のような感じです。

コード:
package demoapp;
import java.io.*;
import java.util.regex.*;
import javax.servlet.*;
import javax.servlet.http.*;

/**
 * HTMLテキスト中のリンクすべてにResponse#encodeURL()を適用する。
 */
public class CookielessSessionFilter implements Filter {
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		
		BufferedTextResponseWrapper responseWrapper = new BufferedTextResponseWrapper(response);
		
		chain.doFilter(request, responseWrapper);
		
		String cookielessSessionHtmlText = encodeUrlForAllUrls((HttpServletResponse)response, responseWrapper.getBuffer());
		
		PrintWriter out = response.getWriter();
		out.print(cookielessSessionHtmlText);
	}
	
	private static Pattern aHrefPattern = Pattern.compile("(<a(\\s+\\w+(=\"[^\"]*\")*)*(\\s+href=\"))([^\"]+)(\"(\\s+\\w+(=\"[^\"]*\")*)*\\s*/?\\s*>)", Pattern.CASE_INSENSITIVE);
	private static Pattern formActionPattern = Pattern.compile("(<form(\\s+\\w+(=\"[^\"]*\")*)*?(\\s+action=\"))([^\"]+)(\"(\\s+\\w+(=\"[^\"]*\")*)*\\s*>)", Pattern.CASE_INSENSITIVE);
	
	/**
	 * htmlText中のHTMLリンクすべてにResponse#encodeURL()を適用する。
	 */
	private String encodeUrlForAllUrls(HttpServletResponse response, CharSequence htmlText) {
		Matcher m;
		StringBuffer sb;
		
		//<a href="...">を変換
		m = aHrefPattern.matcher(htmlText);
		sb = new StringBuffer();		
		while (m.find()) {
			String newHref = m.group(5); //この後URLチェック(必須)
			if (newHref.indexOf(':') == -1) newHref = response.encodeURL(newHref);
			m.appendReplacement(sb, m.group(1) + newHref + m.group(6));
		}
		m.appendTail(sb);
		
		//<form action="...">を変換
		m = formActionPattern.matcher(sb);
		sb = new StringBuffer();
		while (m.find()) {
			String newAction = m.group(5); //この後URLチェック(必須)
			if (newAction.indexOf(':') == -1) newAction = response.encodeURL(newAction);
			m.appendReplacement(sb, m.group(1) + newAction + m.group(6));
		}
		m.appendTail(sb);
		
		return new String(sb);
	}
	
	public void init(FilterConfig config) throws ServletException {
	}
	
	public void destroy() {
	}
	
	static class BufferedTextResponseWrapper extends HttpServletResponseWrapper {
		private StringWriter writer;
		private PrintWriter pw;
		
		public BufferedTextResponseWrapper(ServletResponse response) {
			super((HttpServletResponse)response);
		}
		
		public PrintWriter getWriter() throws IOException {
			writer = new StringWriter();
			pw = new PrintWriter(writer);
			return pw;
		}
		
		public StringBuffer getBuffer() {
			pw.flush();
			return writer.getBuffer();
		}
	}
}



■追記
Tomcat5.x(Servlet2.4仕様準拠)なら、web.xmlに
<filter-mapping>
<filter-name>cookielessSessionFilter</filter-name>
<url-pattern>/hello.jsp</url-pattern>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
を追加することで、Servletからforward()したJSPもFilterで処理できました。
Tomcat4では、ServletからJSPに直接forwardではなく、
一旦Servletに文字列として取り込まないとFilterが効かないようです。
demanotto
会議室デビュー日: 2004/07/29
投稿数: 4
投稿日時: 2004-07-30 10:29
榎本です。

kitoさん>
コードまで記述していただきありがとうございます。
フィルタにすることは私も考えておりました。
今回のケースは携帯電話専用になるので、jsessionidの使用は
ほぼ避けられないのです。

Kissingerさん>
今まではその方法がベターかなと思って使っておりました。
ちなみに、jstlのcタグで、urlを出力すると、cookieが使用できるか
判定した上でjsessionidを自動的に付加してくれます。
が、taglibとボーダフォンの絵文字との相性がよくないので使用しておりません。
(無理にcタグ使うとかえってJavaScript慣れしたデザイナーに渡しにくくなるのでケースバイケースですね(笑))

1

スキルアップ/キャリアアップ(JOB@IT)