Google App Engine for Java(GAE/J)でユーザ認証をフィルタに任せる

横断的な処理はフィルタで処理すると楽です。

最も一般的な例としてユーザ認証が上がるところですので、ユーザ認証を取り上げてみます。
GAEでは、Googleのアカウント認証サービスと連携してユーザ認証を行います。

今回取得する情報は以下の通りです。

  • ユーザ認証の未済
  • ログアウト用Google AccountsのURL
  • ユーザアカウント関連情報(ユーザ認証済の場合)

取得した情報は、セッションに格納します。

UserAcconutFilter.java

import java.io.IOException;
import java.security.Principal;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import com.google.appengine.api.users.UserService;
import com.google.appengine.api.users.UserServiceFactory;

/**
 * ユーザ認証を行うフィルタ
 */
public class UserAcconutFilter implements Filter {

    public void init(FilterConfig arg0) throws ServletException {
    }

    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain filterChain) throws IOException, ServletException {

        UserService userService = UserServiceFactory.getUserService();

        // このフィルタが実行されているウェブページのURIを取得します。
        String thisURL = ((HttpServletRequest) request).getRequestURI();
        
        // このフィルタにリクエストを出したプリンシパルを取得します(認証していない場合、null)
        Principal principal = ((HttpServletRequest) request).getUserPrincipal();

        HttpSession session = ((HttpServletRequest) request).getSession();

        if (principal == null) {
            // ユーザ認証済
            session.setAttribute("isLogin", "LOGOUT");
            // ログイン用のGoogle AccountsのURLを取得します
            session.setAttribute("urlpath", userService.createLoginURL(thisURL));
        } else {
            // ユーザ未認証
            session.setAttribute("isLogin", "LOGIN");
            // ログアウト用のGoogle AccountsのURLを取得します
            session.setAttribute("urlpath", userService.createLogoutURL(thisURL));
      // ユーザアカウント関連情報
            session.setAttribute("userInfo", userService.getCurrentUser());
        }

        filterChain.doFilter(request, response);
    }

    public void destroy() {
    }

}

次に、フィルタとURLパターンをマッピングするため、web.xmlの設定を行います。
今回は、全てのURLパターンにマッピングします。

web.xml

    <filter>
        <filter-name>userAcconutFilter</filter-name>
        <filter-class>[パッケージ名].UserAcconutFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>userAcconutFilter</filter-name>
        <url-pattern>/*</url-pattern>
        <dispatcher>REQUEST</dispatcher>
    </filter-mapping>    

最後に、セッションに格納した情報を基に表示します。
xxx.jsp

<div>
<c:if test="${'LOGOUT' == isLogin}">
<a href="${urlpath}">ログイン</a>
</c:if>
<c:if test="${'LOGIN' == isLogin}">
${userInfo.email}さん | <a href="${urlpath}">ログアウト</a>
</c:if>
</div>


jsp:includeタグで読み込む形にしておくと、便利かなと思います。

<jsp:include page="xxx.jsp" />


もしかしたら、もっと良い方法があるのかもしれません。
その時はご一報ください!