1. 概要

この簡単な記事では、SpringSecurityにおけるロールとGrantedAuthorityの微妙ではあるが重要な違いについて説明します。 役割と権限の詳細については、こちらの記事を参照してください。

2. GrantedAuthority

Spring Securityでは、各GrantedAuthorityを個別の特権と考えることができます。 例としては、 READ_AUTHORITY WRITE_PRIVILEGE 、さらにはCAN_EXECUTE_AS_ROOTなどがあります。 理解しておくべき重要なことは、名前は任意であるということです。

GrantedAuthority を直接使用する場合、たとえば hasAuthority(’READ_AUTHORITY’)のような式を使用する場合、きめ細かい方法でアクセスを制限します

ご存知かもしれませんが、特権を使用することで、権限の概念を参照することもできます。

3. 権威としての役割

同様に、Spring Securityでは、各ロールを、文字列として表され、プレフィックスが「ROLE」である粗粒度のGrantedAuthorityと考えることができます。 hasRole( “ADMIN”)のような式などを使用して、 Role を直接使用する場合、大まかな方法でアクセスを制限しています。

デフォルトの「ROLE」プレフィックスは構成可能ですが、その方法を説明することはこの記事の範囲を超えていることに注意してください。

これら2つの主な違いは、機能の使用方法に付加するセマンティクスです。フレームワークの場合、違いは最小限であり、基本的にまったく同じ方法でこれらを処理します。

4. コンテナとしての役割

フレームワークがロールの概念をどのように使用するかを見てきたので、別の方法についても簡単に説明しましょう。つまり、権限/特権のコンテナーとしてのロールの使用です。

これは、役割に対するより高いレベルのアプローチであり、実装中心の概念ではなく、よりビジネス向けの概念になります。

Spring Securityフレームワークは、概念の使用方法に関するガイダンスを提供していないため、選択は完全に実装固有です。

5. Springセキュリティ構成

/ protected byauthorityへのアクセスをREAD_AUTHORITY のユーザーに制限することで、きめ細かい認証要件を示すことができます。

/ protectedbyroleへのアクセスをROLE_USER のユーザーに制限することで、大まかな承認要件を示すことができます。

このようなシナリオをセキュリティ構成で構成しましょう。

@Override
protected void configure(HttpSecurity http) throws Exception {
    // ...
    .antMatchers("/protectedbyrole").hasRole("USER")
    .antMatchers("/protectedbyauthority").hasAuthority("READ_PRIVILEGE")
    // ...
}

6. 単純なデータ初期化

コアの概念をよりよく理解したので、アプリケーションの起動時にセットアップデータを作成する方法について説明しましょう。

もちろん、これは非常に簡単な方法であり、本番環境でデータを処理する方法ではなく、開発中に一部の予備テストユーザーと一緒に実行に移すことができます。

コンテキスト更新イベントをリッスンします。

@Override
@Transactional
public void onApplicationEvent(ContextRefreshedEvent event) {
    MyPrivilege readPrivilege
      = createPrivilegeIfNotFound("READ_PRIVILEGE");
    MyPrivilege writePrivilege
      = createPrivilegeIfNotFound("WRITE_PRIVILEGE"); 
}

ここでの実際の実装は実際には重要ではありません。通常、使用している永続化ソリューションによって異なります。 重要な点は、コードで使用している権限を維持しているということです。

7. UserDetailsService

UserDetailsServiceの実装は、権限マッピングが行われる場所です。 ユーザーが認証されると、 getAuthorities()メソッドがデータを入力し、UserDetailsオブジェクトを返します。

private Collection<? extends GrantedAuthority> getAuthorities(
  Collection<Role> roles) {
    List<GrantedAuthority> authorities
      = new ArrayList<>();
    for (Role role: roles) {
        authorities.add(new SimpleGrantedAuthority(role.getName()));
        role.getPrivileges().stream()
         .map(p -> new SimpleGrantedAuthority(p.getName()))
         .forEach(authorities::add);
    }
    
    return authorities;
}

8. 例の実行とテスト

GitHubプロジェクトにあるサンプルRolesAuthoritiesApplicationJavaアプリケーションを実行できます。

役割ベースの承認が実際に行われていることを確認するには、次のことを行う必要があります。

  • http:// localhost:8082/protectedbyroleにアクセスします
  • [email protected] として認証します(パスワードは「user」です)
  • 承認の成功に注意してください
  • http:// localhost:8082/protectedbyauthorityにアクセスします
  • 失敗した承認に注意してください

権限ベースの承認が実際に行われていることを確認するには、アプリケーションからログアウトしてから、次のことを行う必要があります。

  • http:// localhost:8082/protectedbyauthorityにアクセスします
  • [email protected]/adminとして認証します
  • 承認の成功に注意してください
  • http:// localhsot:8082/protectedbyroleにアクセスします
  • 失敗した承認に注意してください

9. 結論

このクイックチュートリアルでは、SpringSecurityのRoleGrantedAuthorityの微妙ではあるが重要な違いについて説明しました。