ITお絵かき修行

3歩歩いても忘れないために

サーブレット3.0のセキュリティ系アノテーションを試す

色々試してみたのでまとめる。試したのは以下のアノテーション

@ServletSecurity
@HttpConstraint
@HttpMethodConstraint


【検証環境】
Tomcat7.0.56

【パターン1】特定ロールのユーザのみアクセスを許す場合

※ロール「admin-role」にアクセス許可を与える


1.適当なサーブレットクラスに以下のアノテーションを設定

@ServletSecurity(value=@HttpConstraint(rolesAllowed={"admin-role"}))
@WebServlet(name="hogehoge", urlPatterns="/hogehoge")
public class TestServlet extends HttpServlet {
  ・・・(中略)・・・
}


2.コンテナ側で認証の設定
「設定内容」
・全てのURLにBASIC認証を適用する。
・ユーザ「admin」と「sub」を用意。

・web.xml

<security-constraint>
  <web-resource-collection>
    <web-resource-name>admin page</web-resource-name>
    <url-pattern>/*</url-pattern>
  </web-resource-collection>

  <auth-constraint>
    <role-name>admin-role</role-name>
  </auth-constraint>
    <auth-constraint>
    <role-name>sub-role</role-name>
  </auth-constraint>

  <user-data-constraint>
    <transport-guarantee>NONE</transport-guarantee>
  </user-data-constraint>
</security-constraint>

<security-role>
  <role-name>admin-role</role-name>
</security-role>
<security-role>
  <role-name>sub-role</role-name>
</security-role>

<login-config>
  <auth-method>BASIC</auth-method>
  <realm-name>admin page</realm-name>
</login-config>



tomcat-user.xml ※ルートタグ配下

  <role rolename="admin-role"/>
  <role rolename="sub-role"/>

  <user username="admin" password="password" roles="admin-role"/>
  <user username="sub" password="password" roles="sub-role"/>


3.デプロイ&起動後、ブラウザで「http://localhost:8080/TestServlet/hogehoge」へアクセス。
  結果は以下の通り。
●ユーザ「admin」でアクセス : アクセス可能 (HTTPステータスコード:200)
●ユーザ「sub」でアクセス  : アクセス拒否 (HTTPステータスコード:403)


【パターン2】特定メソッドは認証処理なし、その他のメソッドを使ったアクセスは特定ロールのユーザのみ可能

※GETメソッドは認証処理なし、その他のメソッドを使ったアクセスはロール「admin-role」に属するユーザのみ可能、とする。


1.適当なサーブレットクラスに以下のアノテーションを設定

@ServletSecurity(value=@HttpConstraint(rolesAllowed={"admin-role"}), httpMethodConstraints = {@HttpMethodConstraint("GET")})
@WebServlet(name="hogehoge", urlPatterns="/hogehoge")
public class TestServlet extends HttpServlet {
  ・・・(中略)・・・
}


2.コンテナ側の設定はパターン1の時と同じ

3.デプロイ&起動後、ブラウザで「http://localhost:8080/TestServlet/hogehoge」へアクセス。
  結果は以下の通り。

「結果」
●アクセス可能 (HTTPステータスコード:200) ※ユーザ認証なし


4.認証処理の対象をPOSTメソッドへ変更する。

@ServletSecurity(value=@HttpConstraint(rolesAllowed={"admin-role"}), httpMethodConstraints = {@HttpMethodConstraint("POST")})
@WebServlet(name="hogehoge", urlPatterns="/hogehoge")
public class TestServlet extends HttpServlet {
  ・・・(中略)・・・
}


5.デプロイ&起動後、ブラウザで「http://localhost:8080/TestServlet/hogehoge」へアクセス。
  結果は以下の通り。

「結果」
●ユーザ「admin」でアクセス : アクセス可能 (HTTPステータスコード:200)
●ユーザ「sub」でアクセス  : アクセス拒否 (HTTPステータスコード:403)


【パターン3】特定メソッドは認証処理なし、その他のメソッドを使ったアクセスは特定ロールのユーザのみ可能。ただし特定メソッドはアクセス不可とする
※POSTメソッドは認証処理なし、その他のメソッドを使ったアクセスはロール「admin-role」に属するユーザのみ可能、ただしHEADメソッドはアクセス不可となる。

1.適当なサーブレットクラスに以下のアノテーションを設定

@ServletSecurity(value=@HttpConstraint(rolesAllowed={"admin-role"}),
httpMethodConstraints = {@HttpMethodConstraint("POST"), @HttpMethodConstraint(emptyRoleSemantic
 = javax.servlet.annotation.ServletSecurity.EmptyRoleSemantic.DENY, value = "HEAD")})
@WebServlet(name="hogehoge", urlPatterns="/hogehoge")
public class TestServlet extends HttpServlet {
  ・・・(中略)・・・
}


2.コンテナ側の設定はパターン1の時と同じ

3.デプロイ&起動後、「http://localhost:8080/TestServlet/hogehoge」へアクセス。
  結果は以下の通り。

「結果」
●[HEAD]アクセス拒否 (HTTPステータスコード:503 ※エラーメッセージ:Duplicate method name: HEAD)
●[POST]アクセス可能 (HTTPステータスコード:200)※ユーザ認証なし
●[GET・ロール:admin]アクセス可能 (HTTPステータスコード:200)※ユーザ認証あり(認証失敗すると401)
●[GET・ロール:sub] アクセス拒否 (HTTPステータスコード:403)※ユーザ認証あり(認証失敗すると401)


[備考]ちなみに「@HttpMethodConstraint」におけるアクセス許可の設定については、
   「javax.servlet.annotation.ServletSecurity.EmptyRoleSemantic」の設定が優先される。
   よって、下記の設定においてGETメソッドはアクセス拒否となる。

@ServletSecurity(value=@HttpConstraint(rolesAllowed={"admin-role"}),
httpMethodConstraints = {@HttpMethodConstraint("GET"), @HttpMethodConstraint(emptyRoleSemantic
 = javax.servlet.annotation.ServletSecurity.EmptyRoleSemantic.DENY, value = "GET")})
@WebServlet(name="hogehoge", urlPatterns="/hogehoge")
public class TestServlet extends HttpServlet {
  ・・・(中略)・・・
}


サーブレット&JSPエッセンシャル逆引き大全500の極意

サーブレット&JSPエッセンシャル逆引き大全500の極意