例えば
http://アプリケーションID/private/
というURLにアクセスした場合に、private下にはすべてgoogle認証をかけたい場合、
以下のようなFilterを作成します。
/** * google認証を行うFilterクラス */ public class MemberFilter implements Filter { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException { final HttpServletRequest httpServletRequest = (HttpServletRequest) request; final UserService userService = UserServiceFactory.getUserService(); // リクエストのあったURL final String requestUri = httpServletRequest.getRequestURI(); // googleアカウントにログインしているかを判定するUtilクラス(後述) if (AccountUtils.isGoogleLogin(httpServletRequest) == false) { ((HttpServletResponse) response).sendRedirect(userService.createLoginURL(requestUri)); return; } // ログイン成功 filterChain.doFilter(request, response); } @Override public void destroy() { } @Override public void init(FilterConfig arg0) throws ServletException { } } /** * google認証を判定するUtilクラス */ public class AccountUtils { /** * googleアカウントにログインしているかを判定する。 * * @param request * @return ログインしていればtrue, していなければfalse */ public static boolean isGoogleLogin(final HttpServletRequest request) { final UserService userService = UserServiceFactory.getUserService(); final Principal principal = request.getUserPrincipal(); if (principal == null || userService.isUserLoggedIn() == false) { return false; } return true; } }
以上です。
この例だと、「/private/」にアクセスした場合に、MembeerFilterクラスのdoFilterが呼ばれ、
17行目のif文でgoogleアカウントにログインしているかをチェックし、
falseならばログインページにリダイレクトされます。
ここで、注目して欲しいのが、14行目のrequestUri。
これがログイン後にリダイレクトされるパスを示しています。
18行目のuserService.createLoginURL(requestUri)では、ログインページのパスを作成し、
このパスには、ログイン後にアクセスするURL、つまり今回の例でいう「/private/」が含まれています。
ただ、ここでハマリどころなのですが、実際にアクセスしようとしたURLが「/private/」となっていても、
14行目で取得できるurlは「/private/index.jsp」。
つまり、ログイン後に飛ばされパスは「/private/index.jsp」となってしまいます。
Slim3では、jspファイルに直接アクセスできないようになっているので、
もちろんこれは403エラーになってしまいます。
これを解決するためには、MemberFilterクラスの18行目を、
((HttpServletResponse) response).sendRedirect(userService.createLoginURL(requestUri.replace("index.jsp", "")))
と修正して上げれば、ログイン後に飛ばされるパスから「index.jsp」が削除されるので、
問題なくControllerを経由してページにアクセスできるようになります。
私はカスタムタグの実装で同様の問題にぶつかりました。
返信削除以下のコードでブラウザーから投げられたURIを取得できるみたいです。
((HttpServletRequest)this.pageContext.getRequest()).getAttribute("javax.servlet.forward.request_uri")
なので、Filterでするなら以下でしょうか。
((HttpServletRequest)request).getAttribute("javax.servlet.forward.request_uri")