連載
» 2011年06月10日 00時00分 公開

Tomcat 7も対応したServlet 3.0の変更点 後編Tomcat 7の新機能で何ができるようになるのか?(2)(2/3 ページ)

[藤野圭一,NTT OSSセンタ]

認証用APIとセキュリティ制約の追加

 セキュリティ対応については認証用APIとセキュリティ制約の追加について紹介します。

認証用APIの追加

 Servlet 3.0からServlet APIに以下の認証用メソッドが追加されました。

  • HttpServletRequest#login(String username, String password)
  • HttpServletRequest#logout()
  • HttpServletRequest#authenticate(HttpServletResponse response)

 上記メソッドを利用すると標準のServlet APIを利用して独自の認証プログラムを作成できます。

 認証メソッドは「login(String username, String password)」「authenticate (HttpServletResponse response)」の2種類が用意されています。

 authenticateメソッドではTomcatがデフォルトで提供している認証スキーム(BASIC、CLIENT-CERT、DIGEST、FORM、NONEなど)を利用して認証します。従って、にBASICを指定した場合、authenticateメソッドを呼び出すことで、BASIC認証ができます。

 loginメソッドではTomcatが提供する認証スキームを利用せず、指定されたユーザーとパスワードで直接Realm認証を行います。Realm認証の前後にプログラミングにより自由に処理を追加できるため、独自の認証スキームも作成可能です。

 loginメソッドとauthenticateメソッドのどちらを利用する場合でもRealmを切り替えることでユーザー名とパスワード、ロールを管理するデータベースを切り替えられます(参考:Apache Tomcat 7 Configuration Reference (7.0.14) - The Realm Component)。

 logoutメソッドでは、ログアウト処理を行います。logoutメソッドを呼び出すことで認証情報をリクエストやセッションから削除します。

 以下は、認証用APIの簡単なサンプルです。

LoginServlet

@WebServlet(name = "LoginServlet", urlPatterns = { "/login" })
public class LoginServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String userName = req.getParameter("user");
String password = req.getParameter("password");
try {
if (req.getUserPrincipal() != null) {
resp.getWriter().print("already authenticated!");
}
req.login(userName, password);
} catch (ServletException exp) {
resp.getWriter().print("Login Failed!");
// TODO Handle Exception
}
}
}

 サンプルではリクエストから取得したユーザー名とパスワードを利用して、ログイン認証を行います。

セキュリティ制約と追加

 Servlet 3.0ではsecurity-constraintを追加する方法として3つの方法を提供しています。

  • deployment descriptorにを設定する方法
  • ServletRegistrationインターフェイス(※前回の「Pluggability and Extendibility」の「【2】プログラムによるWebアプリケーションの拡張」を参照)のsetServletSecurityメソッドを利用して設定する方法
  • アノテーション(※前回の「アノテーションで開発が簡単に」参照)を利用して設定する方法

 今回はアノテーションによるセキュリティ制約の追加を紹介します。

 Servlet 3.0から「@ServletSecurity」アノテーションが追加されました。@ServletSecurityではアノテートしたServlet・Filterに対してセキュリティ制約を追加でき、web.xmlのと同様の制約を付与できます。

 また、@ServletSecurityの内部で利用するアノテーションとして「@HttpConstraint」「@HttpMethodConstraint」も追加されています。

 @HttpConstraintでは、@HttpMethodConstraintが制約しない全てのHTTPメソッドに対して適用されるセキュリティ制約を表現するために利用されます。@HttpMethodConstraintは特定のHTTPメソッドのセキュリティ制約を表現するために利用されます。

 今回も基本的な制約の例をサンプルとして掲載します。より詳しい使い方はServlet 3.0の仕様書を確認してください。

 以下では、全てのHTTPメソッドに対して、アクセスを拒否しています。

DenyServlet

@ServletSecurity(@HttpConstraint(EmptyRoleSemantic.DENY))
@WebServlet(name = "DenyServlet", urlPatterns = { "/deny" })
public class DenyServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
}
}

 以下では、全てのHTTPメソッドからのアクセスに対して、「Role="role1"」を要求します。

AllMethodRestrictServlet

@ServletSecurity(value = @HttpConstraint(rolesAllowed = { "role1" }))
@WebServlet(name = "AllMethodRestrictServlet", urlPatterns = { "/all" })
public class AllMethodRestrictServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
resp.getWriter().print("Hello!");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
resp.getWriter().print("Hello!");
}
}

 以下では、GETメソッドからのアクセスに対してはセキュリティ制約なし、それ以外のメソッドに対しては、「Role="role2"」を要求します。

ExcludeGetMethodRestrictServlet

@ServletSecurity(value = @HttpConstraint(rolesAllowed = { "role2" }),
httpMethodConstraints = @HttpMethodConstraint("GET"))
@WebServlet(name = "ExcludeGetMethodRestrictServlet", urlPatterns = { "/excget" })
public class ExcludeGetMethodRestrictServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
resp.getWriter().print("Hello!");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
resp.getWriter().print("Hello!");
}
}

 GETメソッドからのアクセスに対しては「Role="role3"」を要求しています。それ以外のメソッドに対しては、セキュリティ制約はありません。

GetMethodRestrictServlet

ServletSecurity(httpMethodConstraints = @HttpMethodConstraint(value = "GET", rolesAllowed = "role3"))
@WebServlet(name = "GetMethodRestrictServlet", urlPatterns = { "/get" })
public class GetMethodRestrictServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
resp.getWriter().print("Hello!");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
resp.getWriter().print("Hello!");
}
}
 

 次ページで、残りの2つを説明します。

Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。