ひよっこ。

I want to…

SpringSecurity3で権限の階層構造を定義する

Posted by hikaruworld : 2010 12月 24

参考ページ

バージョンはSpringSecurity3.0.5です。

SpringSecurityでは、認証と認可の設定を比較的簡易に設定することが可能ですが、
実際に運用する場合、権限を包括するような設定を行いたくなります。
つまり、以下のように、上位の権限が下位の権限を包括するようなケースです。
管理者 > ユーザ > ゲスト

この仕組みはRoleHierarchyVoterを利用することで設定することが可能です。

認証の仕組みに関して

Springにおける認可の仕組みを簡単に書いておきます。
※MethodSecurtiyのAccessDecisionManagerの認証処理のみです。

特定のユーザで認証処理が通った場合、そのユーザの持つ権限で
該当画面にアクセスできるか認可の処理が実行されます。
その遷移は以下の絵のようになります。

つまり、

  1. 特定ユーザでアクセスする
  2. 1.のもつユーザ権限が該当画面に適切か投票処理(Voter)が行われる。
    Voterが複数ある場合はそれぞれ認可処理が検証される
  3. 2で実行された投票処理の結果をAccessDecisionManagerで判定する。
    AccessDecisionManagerはデフォルトでは、3パターン(いずれか一つがOK,全てOK,Voter単位での多数決)準備されており、任意に設定可能
  4. 3の結果問題なければ画面が表示され、問題あれば403が返される。
  5. 実際の構成

    サンプルプロジェクトはここにUPしています。

    以下、セキュリティ設定のみ抜粋しています。

    <bean id="roleHierarchy" class="org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl">
    	<property name="hierarchy">
    		<value>
    			ROLE_ADMIN > ROLE_USER
    			ROLE_USER > ROLE_GUEST
    		</value>
    	</property>
    </bean>
    <bean id="roleHierarchyVoter" class="org.springframework.security.access.vote.RoleHierarchyVoter">
    	<constructor-arg ref="roleHierarchy" />
    </bean>
    
    <bean id="accessDecisionManager" class="org.springframework.security.access.vote.UnanimousBased">
    	<property name="decisionVoters">
    		<list>
    			<ref bean="roleHierarchyVoter"/>
    			<bean class="org.springframework.security.access.vote.AuthenticatedVoter" />
    		</list>
    	</property>
    </bean>
    

    今回はROLE_ADMIN > ROLE_USER > ROLE_GUESTと階層構造で権限を持たせています。
    まずは、accessDecisionManagerにUnanimousBased(いずれか一つのVoterがOKであればよい)を設定しています。
    そのdecisionVotersとして、AuthenticatedVoterとRoleHierarchyVoterを定義しています。

    RoleHierarchyVoterはコンストラクタインジェクションを用いてRolehierarchyImplを定義しています。

    //org.springframework.security.access.vote.RoleHierarchyVoter
        private RoleHierarchy roleHierarchy = null;
    
        public RoleHierarchyVoter(RoleHierarchy roleHierarchy) {
            Assert.notNull(roleHierarchy, "RoleHierarchy must not be null");
            this.roleHierarchy = roleHierarchy;
        }
        /**
         * Calls the <tt>RoleHierarchy</tt> to obtain the complete set of user authorities.
         */
        @Override
        Collection<GrantedAuthority> extractAuthorities(Authentication authentication) {
            return roleHierarchy.getReachableGrantedAuthorities(authentication.getAuthorities());
        }
    }
    

    RoleHierarchyVoterが実際に認証処理い利用されるのがRoleHierarchyのため、
    この値をRoleHierarchyImplを定義して、プロパティとしてhierarchyを定義します。
    hierarchyは > で各権限を列挙します。

    おまけ

    なお、IS_AUTHENTICATED_FULLYや、
    IS_AUTHENTICATED_ANONYMOUSLYを
    認証処理で利用している場合は、AuthenticatedVoterも
    Voterに入れてあげる必要があります。

    入れてあげないと、

    org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘org.springframework.security.web.access.intercept.FilterSecurityInterceptor#0’: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Unsupported configuration attributes: [IS_AUTHENTICATED_FULLY, IS_AUTHENTICATED_ANONYMOUSLY]

    といった感じで怒られます。
    これは、ここにもあるようにこれらの定義がAuthenticatedVoterで定義されているためです。

    // org.springframework.security.access.vote.AuthenticatedVoter
    
    //~ Static fields/initializers =====================================================================================
    
    public static final String IS_AUTHENTICATED_FULLY
                      = "IS_AUTHENTICATED_FULLY";
    public static final String IS_AUTHENTICATED_REMEMBERED
                      = "IS_AUTHENTICATED_REMEMBERED";
    public static final String IS_AUTHENTICATED_ANONYMOUSLY
                      = "IS_AUTHENTICATED_ANONYMOUSLY";
    

    以上です。

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中

 
%d人のブロガーが「いいね」をつけました。