6.5. 認可¶
Caution
本バージョンの内容は既に古くなっています。最新のガイドラインはこちらからご参照ください。
目次
6.5.1. Overview¶
- Web(リクエストURL)- 特定のURLにアクセスするために必要な権限を設定できる
 
- 画面項目(JSP)- 画面中の特定の要素を表示するために必要な権限を設定できる
 
- メソッド- 特定のメソッドを実行するために必要な権限を設定できる
 
6.5.1.1. アクセス認可(リクエストURL)¶
- ユーザのリクエストに対し、Spring Securityのフィルタチェーンが割り込み処理を行う。
- 認可制御の対象となるURLとリクエストのマッチングを行い、アクセス認可マネージャにアクセス認可の判断を問い合わせる。
- アクセス認可マネージャが、ユーザの権限とアクセス認可情報をチェックし、 必要なロールが割り当てられていない場合は、アクセス拒否例外をスローする。
- 必要なロールが割り当てられている場合は、処理を継続する。
6.5.1.2. アクセス認可(JSP)¶
- JSPから生成されたサーブレットが、アクセス認可マネージャに問い合わせる。
- アクセス認可マネージャが、ユーザの権限とアクセス認可情報をチェックし、 必要なロールが割り当てられていない場合は、タグの内部を評価しない。
- 必要なロールが割り当てられている場合は、タグの内部を評価する。
6.5.1.3. アクセス認可(Method)¶
- Springコンテナがアクセス認可情報をもとに、対象のオブジェクトに対してインターセプタを生成、割り込みさせる。
- インターセプタは設定されたロールをもとにアクセス認可マネージャに問い合わせる。
- アクセス認可マネージャが、ユーザが持つ権限とアクセス認可情報をチェックし、 必要なロールが割り当てられていない場合はアクセス拒否例外をスローする。
- 必要なロールが割り当てられている場合は、処理を継続する(設定により、処理を実行した後に権限をチェックすることもできる)。
6.5.2. How to use¶
6.5.2.1. アクセス認可(リクエストURL)¶
6.5.2.1.1. <sec:intercept-url>要素の設定¶
<sec:http>要素の子要素である<sec:intercept-url>要素に制御対象とするURL、認可するロールを記述することで、- spring-security.xml - <sec:http auto-config="true" use-expressions="true"> <sec:intercept-url pattern="/admin/*" access="hasRole('ROLE_ADMIN')"/> <!-- omitted --> </sec:http> 属性名説明- patternアクセス認可を行う対象のURLパターンを記述する。ワイルドカード「*」、「**」が使用できる。「*」では、同一階層のみが対象であるのに対し、「**」では、指定階層以下の全URLが、認可設定の対象となる。- accessSpring EL式でのアクセス制御式や、アクセス可能なロールを指定する。- methodHTTPメソッド(GETやPOST等)を指定する。指定したメソッドのみに関して、URLパターンとマッチングを行う。指定しない場合は、任意のHTTPメソッドに適用される。主にRESTを利用したWebサービスの利用時に活用できる。- requires-channel「http」、もしくは「https」を指定する。指定したプロトコルでのアクセスを強制する。指定しない場合、どちらでもアクセスできる。上記以外の属性については、B.1.10 <intercept-url>を参照されたい。
- spring-security.xml - <sec:http auto-config="true" use-expressions="true"> <sec:intercept-url pattern="/reserve/*" access="hasAnyRole('ROLE_USER','ROLE_ADMIN')" /> <!-- (1) --> <sec:intercept-url pattern="/admin/*" access="hasRole('ROLE_ADMIN')" /> <!-- (2) --> <sec:intercept-url pattern="/**" access="denyAll" /> <!-- (3) --> <!-- omitted --> </sec:http> 項番説明(1)「/reserve/*」にアクセスするためには、「ROLE_USER」もしくは「ROLE_ADMIN」ロールが必要である。- hasAnyRoleについては、後述する。(2)「/admin/*」にアクセスするためには、「ROLE_ADMIN」ロールが必要である。- hasRoleについては、後述する。(3)- denyAllを全てのパターンに設定し、権限設定が記述されていないURLに対してはどのユーザもアクセス出来ない設定としている。- denyAllについては、後述する。- Note - URLパターンの記述順序について - クライアントからのリクエストに対して、intercept-urlで記述されているパターンに、上から順にマッチさせ、 マッチしたパターンに対してアクセス認可を行う。そのため、パターンの記述は、必ず、より限定されたパターンから記述すること。 
<sec:http>属性にuse-expressions="true"の設定をしたことで、Spring EL式が有効になる。access属性に記述したSpring EL式は真偽値で評価され、式が真の場合に、アクセスが認可される。- spring-security.xml - <sec:http auto-config="true" use-expressions="true"> <sec:intercept-url pattern="/admin/*" access="hasRole('ROLE_ADMIN')"/> <!-- (1) --> <!-- omitted --> </sec:http> - 項番 - 説明 (1)- hasRole('ロール名')を指定することで、ログインユーザが指定したロールを保持していれば真を返す。使用可能なExpression一覧例- 属性名 - 説明 - hasRole('ロール名')ユーザが指定したロールを保持していれば、真を返す。- hasAnyRole('ロール1','ロール2')ユーザが指定したいずれかのロールを保持していれば、真を返す。- permitAll常に真を返す。認証されていない場合も、アクセスできることに注意する。- denyAll常に偽を返す。- isAnonymous()匿名ユーザであれば、真を返す。- isAuthenticated()認証されたユーザならば、真を返す。- isFullyAuthenticated()匿名ユーザ、もしくはRememberMe機能での認証であれば、偽を返す。- hasIpAddress('IPアドレス')リクエストURL、およびJSPタグへのアクセス認可のみで、有効となる。指定のIPアドレスからのリクエストであれば、真を返す。その他、使用可能なSpring EL式は、 Common built-in expressionsを参照されたい。演算子を使用した判定も行うことができる。以下の例では、ロールと、リクエストされたIPアドレス両方に合致した場合、アクセス可能となる。
- spring-security.xml - <sec:http auto-config="true" use-expressions="true"> <sec:intercept-url pattern="/admin/*" access="hasRole('ROLE_ADMIN') and hasIpAddress('192.168.10.1')"/> <!-- omitted --> </sec:http> 使用可能な演算子一覧- 演算子 - 説明 - [式1] and [式2]式1、式2が、どちらも真の場合に、真を返す。- [式1] or [式2]いずれかの式が、真の場合に、真を返す。- ![式]式が真の場合は偽を、偽の場合は真を返す。
Warning
Spring MVCとSpring Securityでは、リクエストとのマッチングの仕組みが厳密には異なっており、この差異を利用してSpring Securityの認可機能を突破し、ハンドラメソッドにアクセスできる脆弱性が存在する。 本事象の詳細は「CVE-2016-5007 Spring Security / MVC Path Matching Inconsistency」を参照されたい。
Spring Framework 4.3.1 以降、Spring Security 4.1.1 以降では MvcRequestMatcher を使用することで本事象は解消されるが、 TERASOLUNA Global Framework for Java (1.x)が使用しているSpring Framework 3.2.17 以降では、Spring MVCで trimTokens プロパティに false を設定した org.springframework.util.AntPathMatcher を使用する必要がある。
<mvc:annotation-driven> <mvc:path-matching path-matcher="pathMatcher" /> </mvc:annotation-driven> <bean id="pathMatcher" class="org.springframework.util.AntPathMatcher"> <property name="trimTokens" value="false" /> </bean>
上記の対策をTERASOLUNA Global Framework for Javaで提供するブランクプロジェクトでは設定しているが、 設定を外すと脆弱性にさらされてしまうので注意する必要がある。
6.5.2.1.2. アクセス認可制御を行わないURLの設定¶
- spring-security.xml<sec:http pattern="/css/*" security="none"/> <!-- 属性の指定順番で(1)~(2) --> <sec:http pattern="/login" security="none"/> <sec:http auto-config="true" use-expressions="true"> <!-- omitted --> </sec:http>
pattern属性に設定を行う対象のURLパターンを記述する。pattern属性を記述しない場合、すべてのパターンにマッチする。security属性にnoneを指定することで、pattern属性に記述されたパスは、Spring Securityフィルタチェインを回避することができる。
6.5.2.1.3. URLパターンでの例外処理¶
org.springframework.security.access.AccessDeniedExceptionがスローされる。org.springframework.security.web.access.ExceptionTranslationFilterに設定されたorg.springframework.security.web.access.AccessDeniedHandlerImplが、エラーコード403を返却する。- spring-security.xml - <sec:http auto-config="true" use-expressions="true"> <!-- omitted --> <sec:access-denied-handler error-page="/accessDeneidPage" /> <!-- (1) --> </sec:http> 項番説明(1)- <sec:access-denied-handler>要素の- error-page属性に、遷移先のパスを指定する。
6.5.2.2. アクセス認可(JSP)¶
<sec:authorize>を利用する。<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %>- <sec:authorize>タグの属性一覧属性名説明- accessアクセス制御式を記述する。真であれば、タグ内が評価される。- url設定したURLに対して権限が与えられている場合に、タグ内が評価される。リンクの表示の制御等に利用する。- methodHTTPメソッド(GETやPOST等)を指定する。 url属性と合わせて利用し、指定したメソッドのみに関して、指定したURLパターンとマッチングを行う。指定しない場合、GETが適用される。- ifAllGranted設定したロールが全て与えられている場合に、タグ内が評価される。ロール階層機能は効かない。- ifAnyGranted設定したロールについて、いずれかが与えられている場合に、タグ内が評価される。ロール階層機能は効かない。- ifNotGranted設定されたロールが与えられていない場合、タグの中身が評価される。ロール階層機能は効かない。- varタグの評価結果を格納するpageスコープの変数を宣言する。同等の権限チェックをページ内で行う場合に利用する。
<sec:authorize>タグの使用例を示す。- spring-security.xml - <div> <sec:authorize access="ROLE_USER"> <!-- (1) --> <p>This screen is for ROLE_USER</p> </sec:authorize> <sec:authorize url="/admin/menu"> <!-- (2) --> <p> <a href="/admin/menu">Go to admin screen</a> </p> </sec:authorize> </div> 項番説明(1)「ROLE_USER」を持つ場合のみ、タグ内が表示される。(2)「/admin/menu」に対してアクセスが認可されている場合、タグ内が表示される。- Warning - <sec:authorize>タグによる認可処理は、画面表示の制御でしかないため、特定の権限でリンクを表示されなくても、URLが推測されれば、直接リンク先のURLにアクセスできてしまう。 そのため、必ず、前述の「アクセス認可(リクエストURL)」、もしくは、後述の「アクセス認可(Method)」を併用して、本質的な認可制御をに行うこと。
6.5.2.3. アクセス認可(Method)¶
org.springframework.security.access.prepost.PreAuthorizeアノテーションを設定すればよい。- spring-security.xml - <sec:global-method-security pre-post-annotations="enabled"/> <!-- (1) --> 項番説明(1)- <sec:global-method-security>要素の- pre-post-annotations属性を- enabledに指定する。デフォルトは- disabledである。
- Javaコード - @Service @Transactional public class UserServiceImpl implements UserSerice // omitted @PreAuthorize("hasRole('ROLE_ADMIN')") // (1) @Override public User create(User user) { // omitted } @PreAuthorize("isAuthenticated()") @Override public User update(User user) { // omitted } } 項番説明(1)アクセス制御式を記述する。メソッドを実行する前に式が評価され、真であれば、メソッドが実行される。偽であれば、- org.springframework.security.access.AccessDeniedExceptionがスローされる。設定可能な値は、<sec:intercept-url>要素の設定で述べたExpressionや、およびSpring Expression Language (SpEL)で記述された式である。- Tip - 上記の設定では - org.springframework.security.access.prepost.PreAuthorize以外にも、以下のアノテーションを使用できる。- org.springframework.security.access.prepost.PostAuthorize
- org.springframework.security.access.prepost.PreFilter
- org.springframework.security.access.prepost.PostFilter
 - これらの詳細はSpring Security マニュアルを参照されたい。 - Note - Spring SecurityではJava標準であるJSR-250の - javax.annotation.security.RolesAllowedアノテーションによる認可制御も可能であるが、- @RolesAllowedではSpELによる記述ができない。- @PreAuthorizeであればSpELを用いて、spring-security.xmlの設定と同じ記法で認可制御- Note - リクエストパスに対する認可制御はControllerのメソッドにアノテーションをつけるのではなく、spring-security.xmlに設定を行うことを推奨する。 - ServiceがWeb経由でしか実行されず、リクエストパスのすべてのパターンが認可制御されているのであればServiceの認可制御は行わなくても良い。 Serviceがどこから実行されるか分からず、認可制御が必要な場合にアノテーションを使用するとよい。 
6.5.3. How to extend¶
6.5.3.1. ロール階層機能¶
Spring Security 設定ファイル
<sec:http auto-config="true" use-expressions="true">
    <sec:intercept-url pattern="/user/*" access="hasAnyRole('ROLE_USER')" />
    <!-- omitted -->
</sec:http>
6.5.3.1.1. 共通設定¶
org.springframework.security.access.hierarchicalroles.RoleHierarchy クラスのBean定義を行う。- spring-security.xml - <bean id="roleHierarchy" class="org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl"> <!-- (1) --> <property name="hierarchy"> <value> <!-- (2) --> ROLE_ADMIN > ROLE_STAFF ROLE_STAFF > ROLE_USER </value> </property> </bean> 項番説明(1)- RoleHierarchyのデフォルト- org.springframework.security.access.hierarchicalroles.RoleHierarchyImplクラスを指定する。(2)- hierarchyプロパティに階層関係を定義する。書式:[上位ロール] > [下位ロール]例では、STAFFはUSERに認可されたすべてのリソースに、アクセスできる。ADMINはUSER、STAFFに認可されたすべてのリソースに、アクセスできる。
6.5.3.1.2. アクセス認可(リクエストURL)、アクセス認可(JSP)での使用方法¶
- spring-security.xml - <bean id="webExpressionHandler" class="org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler"> <!-- (1) --> <property name="roleHierarchy" ref="roleHierarchy"/> <!-- (2) --> </bean> <sec:http auto-config="true" use-expression="true"> <!-- omitted --> <sec:expression-handler ref="webExpressionHandler" /> <!-- (3) --> </sec:http> 項番説明(1)クラスに- org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandlerを指定する。(2)- roleHierarchyプロパティに- RoleHierarchyのBean IDをプロパティに設定する。(3)- expression-handler要素に、- org.springframework.security.access.expression.SecurityExpressionHandlerを実装したハンドラクラスのBean IDを指定する。
6.5.3.1.3. アクセス認可(Method)での使用方法¶
- spring-security.xml - <bean id="methodExpressionHandler" class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler"> <!-- (1) --> <property name="roleHierarchy" ref="roleHierarchy"/> <!-- (2) --> </bean> <sec:global-method-security pre-post-annotations="enabled"> <sec:expression-handler ref="methodExpressionHandler" /> <!-- (3) --> </sec:global-method-security> 項番説明(1)クラスに- org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandlerを指定する。(2)- roleHierarchyプロパティに- RoleHierarchyのBean IDをプロパティに設定する。(3)- expression-handler要素に、- org.springframework.security.access.expression.SecurityExpressionHandlerを実装したハンドラクラスのBean IDを指定する。



