ようやく、この問題が解決。解決方法は、PortalRequestWrapperでHttpServletRequestWrapperを継承するのではなく、HttpServletRequestをインターフェースする。原因は、コンテキストパスがApplicationDispatcherで異なるみたいで、ApplicationHttpRequestでcrossContextがtrueになり、セッションを新規生成するみたい。もう少し、Tomcatのコードをみた方がいいかな。
カテゴリー: Apache
PortalFilter問題 その2
どうやら、Tomcatが親RequestをApplicationHttpRequestに差し替えられるのが原因に見える。Tomcatの以下のApplicationDispatcherのコードで変えられていると思われる。
/** * Create and return a request wrapper that has been inserted in the * appropriate spot in the request chain. */ private ServletRequest wrapRequest() { // Locate the request we should insert in front of ServletRequest previous = null; ServletRequest current = outerRequest; while (current != null) { if ("org.apache.catalina.servlets.InvokerHttpRequest". equals(current.getClass().getName())) break; // KLUDGE - Make nested RD.forward() using invoker work if (!(current instanceof ServletRequestWrapper)) break; if (current instanceof ApplicationHttpRequest) break; if (current instanceof ApplicationRequest) break; if (current instanceof Request) break; previous = current; current = ((ServletRequestWrapper) current).getRequest(); } // Instantiate a new wrapper at this point and insert it in the chain ServletRequest wrapper = null; if ((current instanceof ApplicationHttpRequest) || (current instanceof Request) || (current instanceof HttpServletRequest)) { // Compute a crossContext flag HttpServletRequest hcurrent = (HttpServletRequest) current; boolean crossContext = false; if ((outerRequest instanceof ApplicationHttpRequest) || (outerRequest instanceof Request) || (outerRequest instanceof HttpServletRequest)) { HttpServletRequest houterRequest = (HttpServletRequest) outerRequest; Object contextPath = houterRequest.getAttribute (Globals.INCLUDE_CONTEXT_PATH_ATTR); if (contextPath == null) { // Forward contextPath = houterRequest.getContextPath(); } crossContext = !(context.getPath().equals(contextPath)); } wrapper = new ApplicationHttpRequest (hcurrent, context, crossContext); } else { wrapper = new ApplicationRequest(current); } if (previous == null) outerRequest = wrapper; else ((ServletRequestWrapper) previous).setRequest(wrapper); wrapRequest = wrapper; return (wrapper); }
うーん、ApplicationHttpRequestについて、理解する必要があるな・・・。
PortalFilter
いや~、はまっている。adminで初めてログインしたときにパスワードを変更するところではまっている。中身について説明すると、PasswordCredentialValveImpl#invokeでパスワードの有効期限が切れていたりすると、プロファイルでsecurityに定義された流れでPSMLを探す。つまり、PasswordCredentialValveImplで表示するページをコントロールしている。adminで初めてログインするときには、PasswordCredential#isUpdateRequiredがtrueになっているため、ページが飛ばされる。っで、my-account.psmlが表示され、パスワード変更ポートレットが表示される。次に、新しいパスワードを入力し、送信すると、ChangePasswordPortletのprocessActionで新しいSubjectを生成して、JetspeedRequestContextのセッション(つまり、ポートレットのセッションではなく、J2のセッション)に入れる。で、このセッションで問題が発生している!PortalFilterをかませたときだけ、どうやら、新規にセッションが作られているみたいだ。そういわけで、謎のセッションに新しいSubjectを入れて、結局、PortalFilterでセッションから古いSubjectを再度取得して、isUpdateRequiredがtrueのままなので、再び、my-account.psmlを表示する。まずは、なぜ、PortalFilterをかませたときだけ、謎のセッションが来るのかを突き止める必要がある。現在の予想では、ラップしているところに問題があるような気もしている。コード内では、getRequest()でラップしたやつをとったりする場合がいくつかあるし。というわけで、調査中。結構、ややこしいので、調べるのに時間がかかっているな・・・。