Spring SecurityでのRoleとGrantedAuthorityの違い


227

Spring Securityには、アクセスを承認/制御する権限GrantedAuthority取得するためのインターフェースなどの概念と実装があります。

createSubUsersdeleteAccountsなどの許可された操作を管理者に許可します(ロール付きROLE_ADMIN)。

オンラインで見ているチュートリアル/デモと混同しています。私は読んだものをつなげようとしますが、2つを同じように扱っていると思います。

文字列をhasRole消費していGrantedAuthorityますか?私は間違いなく理解においてそれを間違っています。これらはSpring Securityで概念的に何ですか?

ユーザーの役割を、その役割の権限とは別に保管するにはどうすればよいですか?

私はまたorg.springframework.security.core.userdetails.UserDetailsUser(最後のGrantedAuthorityをメモする)を消費する認証プロバイダー参照DAOで使用されるインターフェースも調べています。

public User(String username, 
            String password, 
            boolean enabled, 
            boolean accountNonExpired,
            boolean credentialsNonExpired, 
            boolean accountNonLocked, 
            Collection<? extends GrantedAuthority> authorities)

または、他の2つを区別する他の方法はありますか?それともサポートされていませんか?私たちは自分で作る必要がありますか?

回答:


365

GrantedAuthorityを「許可」または「権利」と考えてください。それらの「許可」は(通常)文字列として(getAuthority()メソッドを使用して)表現されます。これらの文字列を使用すると、権限を識別し、有権者が何かへのアクセスを許可するかどうかを決定できます。

ユーザーをセキュリティコンテキストに入れることにより、ユーザーにさまざまなGrantedAuthority(権限)を付与できます。通常は、必要なGrantedAuthoritiesを返すUserDetails実装を返す独自のUserDetailsS​​erviceを実装することでこれを行います。

ロール(多くの例で使用されている)は、ロールがプレフィックスで始まるGrantedAuthorityであることを示す命名規則を持つ単なる「権限」ROLE_です。これ以上はありません。ロールは、GrantedAuthority-「許可」-「権利」です。ROLE_Springのセキュリティでは、プレフィックス付きのロールが特別に処理される場所がたくさんありROLE_ます。たとえば、RoleVoterでは、プレフィックスがデフォルトとして使用されます。これにより、ROLE_プレフィックスなしでロール名を提供できます。Springセキュリティ4より前は、この「役割」の特別な処理は一貫して行われておらず、権限と役割は同じように扱われることが多かった(たとえば、hasAuthority()hasRole())。Spring Security 4では、ロールの扱いがより一貫しており、「ロール」(RoleVoterhasRole式など)を処理するコードは常にROLE_プレフィックスを追加します。つまり、プレフィックスが自動的に追加さhasAuthority('ROLE_ADMIN')れるのと同じです。詳細については、Spring Security 3から4 への移行ガイドを参照してください。hasRole('ADMIN')ROLE_

しかし、それでも:ロールは特別なROLE_接頭辞を持つ単なる権限です。したがって、Springのセキュリティ3はと@PreAuthorize("hasRole('ROLE_XYZ')")同じ@PreAuthorize("hasAuthority('ROLE_XYZ')")で、Springのセキュリティ4はと@PreAuthorize("hasRole('XYZ')")同じ@PreAuthorize("hasAuthority('ROLE_XYZ')")です。

ユースケースについて:

ユーザーには役割があり、役割は特定の操作を実行できます。

であなたは終わる可能性GrantedAuthoritiesの役割のためにユーザーが属すると役割が実行できる操作。GrantedAuthorities役割については、接頭辞を持っているROLE_と操作は接頭辞を持っていますOP_。操作当局のための例は以下のようになりOP_DELETE_ACCOUNTOP_CREATE_USEROP_RUN_BATCH_JOBなどの役割をすることができROLE_ADMINROLE_USERROLE_OWNERなど

GrantedAuthority次の(疑似コード)の例のように、エンティティーを実装させることができます。

@Entity
class Role implements GrantedAuthority {
    @Id
    private String id;

    @ManyToMany
    private final List<Operation> allowedOperations = new ArrayList<>();

    @Override
    public String getAuthority() {
        return id;
    }

    public Collection<GrantedAuthority> getAllowedOperations() {
        return allowedOperations;
    }
}

@Entity
class User {
    @Id
    private String id;

    @ManyToMany
    private final List<Role> roles = new ArrayList<>();

    public Collection<Role> getRoles() {
        return roles;
    }
}

@Entity
class Operation implements GrantedAuthority {
    @Id
    private String id;

    @Override
    public String getAuthority() {
        return id;
    }
}

あなたがデータベース内に作成した役割や業務のIDは、例えばGrantedAuthority表現だろうROLE_ADMINOP_DELETE_ACCOUNTなどユーザーが認証されると、)すべてすべての役割のGrantedAuthoritiesとは、対応する操作はUserDetails.getAuthorities(から返されていることを確認してください方法。

例:idの管理者ロールにROLE_ADMINは、操作OP_DELETE_ACCOUNTOP_READ_ACCOUNTOP_RUN_BATCH_JOB割り当てられています。IDのユーザー役割にROLE_USERは操作がありますOP_READ_ACCOUNT

結果のセキュリティコンテキストで管理者のログはGrantedAuthoritiesがあります場合: ROLE_ADMINOP_DELETE_ACCOUNTOP_READ_ACCOUNTOP_RUN_BATCH_JOB

ユーザーがそれをログに記録した場合、それがあります: ROLE_USEROP_READ_ACCOUNT

UserDetailsS​​erviceは、すべての役割とそれらの役割のすべての操作を収集し、返されたUserDetailsインスタンスのメソッドgetAuthorities()でそれらを利用できるようにします。


2
ありがとうございました!「hasRole( 'rolename')」がSpring 4で機能しなかった理由をどこでも探していました->ドキュメントがすぐに読み飛ばされませんでした。簡単な「検索と置換」で、軌道に戻りました!
ヨルゲンSKÄRフィッシャー

12
これは素晴らしい答えです。少し異なって説明することを明確にすることの1つはhasRole('xyz')、Spring Security 4では、ROLE_接頭辞があるhasAuthority('xyz')ことを期待するのに対し、は接頭辞を期待せず、渡されたものを正確に評価します。このソリューションを使用しましたがhasRole('OP_MY_PERMISSION')ROLE_の接頭辞が必要でした。代わりに、hasAuthority('OP_MY_PERMISSION')接頭辞がないため、を使用しているはずです。
randal4 2016年

@jamesあなたはこの質問を見ることができstackoverflow.com/questions/41500031/...
saurabhクマー

1
JSTLでは<sec:authorize access="hasRole('ADMIN')">、springframework.org / security / tags は<sec:authorize access="hasRole('ROLE_ADMIN')">
Alex78191

1
はい。OP_は単なる任意のプレフィックスです。ROLE_は、一部の春の実装で特別な意味を持っています。
James

9

AFAIK GrantedAuthorityとロールは春のセキュリティで同じです。GrantedAuthorityのgetAuthority()文字列が役割です(デフォルトの実装ではSimpleGrantedAuthority)。

あなたのケースでは、階層的な役割を使用することができます

<bean id="roleVoter" class="org.springframework.security.access.vote.RoleHierarchyVoter">
    <constructor-arg ref="roleHierarchy" />
</bean>
<bean id="roleHierarchy"
        class="org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl">
    <property name="hierarchy">
        <value>
            ROLE_ADMIN > ROLE_createSubUsers
            ROLE_ADMIN > ROLE_deleteAccounts 
            ROLE_USER > ROLE_viewAccounts
        </value>
    </property>
</bean>

あなたが探している正確なゾルではありませんが、それが役に立てば幸いです

編集:コメントに返信

役割は、春のセキュリティにおける許可のようなものです。hasRoleでintercept-urlを使用すると、どの役割/権限で許可される操作を非常に細かく制御できます。

アプリケーションで処理する方法は、view_account、delete_account、add_accountなどの各操作(または残りのURL)の権限(つまりロール)を定義します。次に、admin、guest_user、normal_userなどの各ユーザーの論理プロファイルを作成します。プロファイルは、Spring-Securityに関係なく、権限の論理的なグループ化にすぎません。新しいユーザーが追加されると、それにプロファイルが割り当てられます(許可されたすべての権限を持っています)。これで、ユーザーが何らかのアクションを実行しようとすると、そのアクションのアクセス許可/ロールがユーザーgrantAuthoritiesに対してチェックされます。

また、defaultn RoleVoterはプレフィックスROLE_を使用するため、ROLE_で始まるすべての権限はロールと見なされます。ロール有権者でカスタムRolePrefixを使用し、Springセキュリティで使用することで、このデフォルトの動作を変更できます。


1
ご協力ありがとうございました。階層は別のものに見えます。私が今それを行うことを考えている方法(私がSpring Securityを使用する必要がある場合)は、ロールと権限の両方を同じリストに格納し、hasRole述語を使用して両方のチェックを実行することです。それについてもっと考えます-これはおそらくSpring Securityの人たちによって意図的に残されていますか?役割と特権/権限の完全なリスト、またはその他の承認アプリケーションでhasRoleを使用してチェックする以外に、intercept-urlを使用する可能性はありますか?また、ROLE_をプレフィックスする必要は何ですか?慣習ですか?
Chinmay 2013年

7

これらの概念間の関係を理解するもう1つの方法は、ROLEを機関のコンテナとして解釈することです。

権限は、特定のアクションを対象とするきめ細かな権限であり、特定のデータスコープまたはコンテキストと組み合わされる場合があります。たとえば、読み取り、書き込み、管理は、特定の範囲の情報に対するさまざまなレベルのアクセス許可を表すことができます。

また、ROLEがコントローラーに到達する前にリクエストフィルターによってフィルターされている間、権限はリクエストの処理フローの深いところに適用されます。ベストプラクティスは、ビジネスレイヤーのコントローラーを通過する当局の実施の実装を規定しています。

一方、ROLESは、一連のパーミッションの大まかな表現です。ROLE_READERには読み取りまたは表示の権限しかありませんが、ROLE_EDITORには読み取りと書き込みの両方の権限があります。ロールは主に、httpなどのリクエスト処理の外部での最初のスクリーニングに使用されます。... .antMatcher(...)。hasRole(ROLE_MANAGER)

リクエストのプロセスフローの深部で実施される権限により、許可をよりきめ細かく適用できます。たとえば、ユーザーには、リソースの第1レベルに対する読み取り/書き込み権限がありますが、サブリソースに対する読み取りのみが可能です。ROLE_READERを使用すると、このリソースを編集するための書き込み権限が必要になるため、最初のレベルのリソースを編集する権限が制限されますが、@ PreAuthorizeインターセプターがサブリソースを編集するための暫定をブロックする可能性があります。

ジェイク


2

他の人が述べたように、私はロールをより細かいパーミッションのためのコンテナと考えています。

Hierarchy Roleの実装には、これらのきめ細かい権限を細かく制御できないことがわかりました。
そこで、関係を管理し、許可された権限としてセキュリティコンテキストにアクセス許可を注入するライブラリを作成しました。

アプリに一連の権限(CREATE、READ、UPDATE、DELETEなど)があり、ユーザーのロールに関連付けられている場合があります。

または、READ_POST、READ_PUBLISHED_POST、CREATE_POST、PUBLISH_POSTなどのより具体的な権限

これらの権限は比較的静的ですが、役割と権限の関係は動的な場合があります。

例-

@Autowired 
RolePermissionsRepository repository;

public void setup(){
  String roleName = "ROLE_ADMIN";
  List<String> permissions = new ArrayList<String>();
  permissions.add("CREATE");
  permissions.add("READ");
  permissions.add("UPDATE");
  permissions.add("DELETE");
  repository.save(new RolePermissions(roleName, permissions));
}

APIを作成して、これらの権限とロールの関係を管理できます。

別の回答をコピー/貼り付けしたくないので、SOに関するより完全な説明へのリンクを示します。
https://stackoverflow.com/a/60251931/1308685

実装を再利用するために、リポジトリを作成しました。貢献してください!
https://github.com/savantly-net/spring-role-permissions

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.