T2+GAE+guice+AIR 多分その3 認証処理を作ってみる。
まえのエントリーでも書きましたが、
T2はその拡張性の高さも使いやすい理由の一つだと思います。
T2では、各処理のポイントに拡張する方法を提供しているので、
非常に扱いやすのです。
拡張を差し込むという意味では、インターセプターもいますが、
利用してみたところ、動きが見えずらい、いつ動くの?
との声が多く結構難しんだな〜と思いました。
てことで、T2のPluginを使って、認証処理を作成してみました。
実装
前回のエントリーにも書いてますが、若干GuiceAdapterを拡張してますので、
あしからず。
まずAnnotationです。
Pageクラスのクラスまたはメソッドにつけて、
認証するかしないかを判断します。
package jp.stk.gae.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE , ElementType.METHOD} ) public @interface Auth { public boolean onlyAdmin() default false; public boolean canUseNonUser() default false; }
次にPluginです。
抽象クラス:AuthPlugin
package jp.stk.gae.plugin; import org.t2framework.t2.plugin.AbstractPlugin; public abstract class AuthPlugin extends AbstractPlugin { }
実装クラス:AuthPluginImpl
package jp.stk.gae.plugin.impl; import java.lang.reflect.Method; import javax.servlet.http.HttpServletRequest; import jp.stk.gae.annotation.Auth; import jp.stk.gae.exception.AuthException; import jp.stk.gae.plugin.AuthPlugin; import org.t2framework.commons.meta.MethodDesc; import org.t2framework.commons.util.Logger; import org.t2framework.commons.util.StringUtil; import org.t2framework.t2.action.ActionContext; import org.t2framework.t2.contexts.HttpMethod; import org.t2framework.t2.spi.Navigation; import com.google.appengine.api.users.UserService; import com.google.inject.Inject; public class AuthPluginImpl extends AuthPlugin { @SuppressWarnings("unused") private final static Logger logger = Logger.getLogger(AuthPluginImpl.class); @Inject UserService userService; @Inject HttpServletRequest request; @Override public Navigation beforeActionInvoke(ActionContext actionContext, MethodDesc targetMethod, Object page, Object[] args) { Method m = targetMethod.getMethod(); Class<?> c = m.getDeclaringClass(); Auth classAnn = c.getAnnotation(Auth.class); Auth methodAnn = m.getAnnotation(Auth.class); if (classAnn == null && methodAnn == null) { return super.beforeActionInvoke(actionContext, targetMethod, page, args); } Auth auth = methodAnn != null ? methodAnn : classAnn; if (!userService.isUserLoggedIn()) { addLoginLink2Request(actionContext); if (auth.onlyAdmin()) { throw new AuthException("この画面は利用できません。"); } if (!auth.canUseNonUser()) { throw new AuthException("ログインしていない方は、利用できません。"); } return super.beforeActionInvoke(actionContext, targetMethod, page, args); } addLogoutLink2Request(actionContext); if (auth.onlyAdmin() && !userService.isUserAdmin()) { throw new AuthException("この画面は利用できません。"); } return super.beforeActionInvoke(actionContext, targetMethod, page, args); } private void addLoginLink2Request(ActionContext actionContext) { if (actionContext.getRequest().isAjaxRequest() || actionContext.getRequest().isAmfRequest()) { return; } String url = actionContext.getRequest().getRequestURI(); String queryString = null; if (actionContext.getRequest().getMethod() != HttpMethod.GET) { url = "/"; queryString = ""; } else { queryString = request.getQueryString(); } String redirectUrl = url; if (!StringUtil.isEmpty(queryString)) { redirectUrl += url.contains("?") ? "&" : "?"; redirectUrl += queryString; } String loginUrl = userService.createLoginURL(redirectUrl); actionContext.getRequest().setAttribute("loginUrl", loginUrl); } private void addLogoutLink2Request(ActionContext actionContext) { if (actionContext.getRequest().isAjaxRequest() || actionContext.getRequest().isAmfRequest()) { return; } String logoutUrl = userService.createLogoutURL("/"); actionContext.getRequest().setAttribute("logoutUrl", logoutUrl); } }
であとはModuleとかでこのPluginを設定して、
認証したい、ページにAuthアノテーションを付ければ
OKです。