GeekFactory

int128.hatenablog.com

OpenID認証によるアクセス制御フィルタ

2010-06-05 お詫び:ソースコードに間違いがありましたので修正しました。OpenIDのIdentifierを取得するには getUserId() ではなく getFederatedIdentity() を使用してください。

データ変換タスクをTaskQueueに投入するページなど、開発者のみアクセスを許可したいURLにOpenID認証をかける方法を紹介します。

まず OpenID認証によるシングルサインオン - GeekFactory の通りにOpenID認証を有効にしておきます。この時点で認証は有効になっています。これから認可を設定しましょう。

例えば http://xxx.appspot.com/util/* は開発者のみアクセスを許可したい場合、web.xmlに以下を記述します。

  <security-constraint>
    <web-resource-collection>
      <web-resource-name>Administration Utilities</web-resource-name>
      <url-pattern>/util/*</url-pattern>
    </web-resource-collection>
    <auth-constraint>
      <role-name>*</role-name>
    </auth-constraint>
  </security-constraint>
  <filter>
    <filter-name>LoginFilter</filter-name>
    <filter-class>org.hidetake.app.LoginFilter</filter-class>
    <init-param>
      <param-name>uid</param-name>
      <!-- アクセスを許可したいOpenID Identifierを記述します -->
      <param-value>http://www.hatena.ne.jp/int128/</param-value>
    </init-param>
  </filter>

/util/* にアクセスすると LoginFilter#doFilter() が実行されます。LoginFilterクラスを作成しましょう。

public class LoginFilter implements Filter
{
	private String userId;

	public void destroy() {}

	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
	throws IOException, ServletException
	{
		UserService userService = UserServiceFactory.getUserService();
		User currentUser = userService.getCurrentUser();
		String currentId = currentUser.getFederatedIdentity(); //2010-06-05: getUserId()は間違っていたので修正しました

		// Identiferの一致を確認する
		if(!userId.equals(currentId)) {
			throw new IllegalStateException("invalid user: " + currentId);
		}

		chain.doFilter(request, response);
	}

	public void init(FilterConfig fConfig) throws ServletException
	{
		String uid = fConfig.getInitParameter("uid");
		if(uid == null) {
			throw new IllegalArgumentException("no parameter given: uid");
		}
		userId = uid;
	}
}

これでフィルタによるアクセス制御が有効になりました。ほんの少しのコード追加でセキュリティを強化できますのでお試しあれ。