GeekFactory

int128.hatenablog.com

security-constraintによる認証と認可について

web.xml で security-constraint を記述すると、指定したURLパターンについてOpenID Providerによる認証が有効になります。認可の設定は role-name で指定します。

role-name=*

すべてのユーザに対してアクセスを許可します。

アプリケーションでは User#getFederatedIdentity() の値をチェックし、必要に応じてアクセス制御を行います。

<security-constraint>
  <web-resource-collection>
    <web-resource-name>Admin Utilities</web-resource-name>
    <url-pattern>/admin/*</url-pattern>
  </web-resource-collection>
  <auth-constraint>
    <role-name>*</role-name>
  </auth-constraint>
</security-constraint>

role-name=admin

アプリケーションの所有者(自分のGoogleアカウント)に対してのみアクセスを許可します。それ以外のユーザには 403 Forbidden が返ります。

自分しか使わないツールのURLには admin を指定しておくとよいでしょう。

<security-constraint>
  <web-resource-collection>
    <web-resource-name>Admin Utilities</web-resource-name>
    <url-pattern>/admin/*</url-pattern>
  </web-resource-collection>
  <auth-constraint>
    <role-name>admin</role-name>
  </auth-constraint>
</security-constraint>

指定したユーザにアクセスを許可する方法

security-constraintによる認可では上記の2種類しか指定できないため、柔軟性に欠けます。

そこで、指定したユーザのみにアクセスを許可するサーブレットフィルタを書いてみました。

<filter>
  <filter-name>LoginFilter</filter-name>
  <filter-class>org.hidetake.app.healthcheck2.util.LoginFilter</filter-class>
  <init-param>
    <param-name>allowUserId</param-name>
    <param-value>http://www.hatena.ne.jp/int128/</param-value>
  </init-param>
</filter>
<filter-mapping>
  <filter-name>LoginFilter</filter-name>
  <url-pattern>/util/*</url-pattern>
</filter-mapping>
public class LoginFilter implements Filter
{
private final UserService userService = UserServiceFactory.getUserService();
private String allowUserId;

public void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws IOException, ServletException
{
  if(AppEngineUtil.isProduction()) {
    User user = userService.getCurrentUser();
    if(user != null) {
      if(allowUserId.equals(user.getFederatedIdentity())) {
        chain.doFilter(request, response);
      }
      else {
        response.setStatus(403);
        response.setContentType("text/plain");
        response.getWriter().append("403 Forbidden");
      }
    }
    else {
      response.sendRedirect(userService.createLoginURL(request.getRequestURI(),
          request.getServerName(),
          allowUserId,
          Collections.<String>emptySet()));
    }
  }
  else {
    chain.doFilter(request, response);
  }
}
}
https://github.com/int128/healthcheck2/blob/3ac977bb4f9979f3bdf4802d61138d970d50443a/src/org/hidetake/app/healthcheck2/util/LoginFilter.java