mcpField
U
unit-test-security-authorization

unit-test-security-authorization

github.com/giuseppe-trisciuoglioテスト・品質3653.7k 回インストール7 週間前に更新
リポジトリ

unit-test-security-authorization について

完全なセキュリティコンテキストを読み込まずに Spring Security の認可ルールをテストするスキルです。Java 開発者向けに、ロール判定、メソッドセキュリティのアノテーション、カスタム権限評価器、アクセス拒否のテスト方法を説明します。

主な機能

  1. 01`@PreAuthorize` などのアノテーションをテスト
  2. 02`@WithMockUser` によるユーザーの再現
  3. 03ロール別の許可・拒否ケースの確認
  4. 04カスタム権限評価器のテスト
  5. 05メソッドセキュリティ設定の確認

活用シーン

  1. 01管理者限定のサービスメソッドを検証
  2. 02ユーザーロールに応じたアクセスルールをテスト
  3. 03リソース所有者に基づく権限判定を確認
  4. 04未認証・未許可の呼び出しが拒否されることを確認

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/giuseppe-trisciuoglio/developer-kit --skill unit-test-security-authorization

インストール後、Claude Code で/unit-test-security-authorizationを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
advanced-authorization.md
basic-testing.md
complete-examples.md
setup.md

詳細

単体テストでのセキュリティと認可

概要

このスキルでは、@PreAuthorize、@Secured、@RolesAllowed、カスタム権限評価器を使用して、Spring Security の認可ロジックを単体テストするパターンを紹介します。ロールベースのアクセス制御(RBAC)、式ベースの認可、カスタム権限評価器のテストや、Spring Security のコンテキスト全体を使用せずにアクセス拒否のシナリオを検証する方法を扱います。

使用する場面

次の場合にこのスキルを使用します。

  • @PreAuthorize と @Secured によるメソッドレベルセキュリティをテストする
  • ロールベースのアクセス制御(RBAC)をテストする
  • カスタム権限評価器をテストする
  • アクセス拒否のシナリオを検証する
  • 認証済みプリンシパルによる認可をテストする
  • Spring Security のコンテキスト全体を使用せず、高速に認可テストを行いたい

手順

以下の手順で Spring Security の認可をテストします。

1. セキュリティテスト用の依存関係を設定する

テストの依存関係に spring-security-test を追加します。

<dependency>
  <groupId>org.springframework.security</groupId>
  <artifactId>spring-security-test</artifactId>
  <scope>test</scope>
</dependency>
2. テスト設定でメソッドセキュリティを有効にする
@Configuration
@EnableMethodSecurity
class TestSecurityConfig { }
3. @WithMockUser を使用してテストする
@Test
@WithMockUser(roles = "ADMIN")
void shouldAllowAdminAccess() {
  assertThatCode(() -> service.deleteUser(1L))
    .doesNotThrowAnyException();
}

@Test
@WithMockUser(roles = "USER")
void shouldDenyUserAccess() {
  assertThatThrownBy(() -> service.deleteUser(1L))
    .isInstanceOf(AccessDeniedException.class);
}
4. カスタム権限評価器をテストする
@Test
void shouldGrantPermissionToOwner() {
  Authentication auth = new UsernamePasswordAuthenticationToken(
    "alice", null, List.of(new SimpleGrantedAuthority("ROLE_USER"))
  );
  Document doc = new Document(1L, "Test", new User("alice"));

  boolean result = evaluator.hasPermission(auth, doc, "WRITE");
  assertThat(result).isTrue();
}
5. セキュリティが有効であることを検証する

テストが予期せず成功する場合は、以下のアサーションを追加してセキュリティが適用されていることを確認します。

@Test
void shouldRejectUnauthorizedWhenSecurityEnabled() {
  assertThatThrownBy(() -> service.deleteUser(1L))
    .isInstanceOf(AccessDeniedException.class);
}

クイックリファレンス

アノテーション説明例
@PreAuthorize呼び出し前の認可@PreAuthorize("hasRole('ADMIN')")
@PostAuthorize呼び出し後の認可@PostAuthorize("returnObject.owner == authentication.name")
@Securedシンプルなロールベースのセキュリティ@Secured("ROLE_ADMIN")
@RolesAllowedJSR-250 標準@RolesAllowed({"ADMIN", "MANAGER"})
@WithMockUserテスト用アノテーション@WithMockUser(roles = "ADMIN")

例

基本的な @PreAuthorize テスト
@Service
public class UserService {
  @PreAuthorize("hasRole('ADMIN')")
  public void deleteUser(Long userId) {
    // delete logic
  }
}

// Test
@Test
@WithMockUser(roles = "ADMIN")
void shouldAllowAdminToDeleteUser() {
  assertThatCode(() -> service.deleteUser(1L))
    .doesNotThrowAnyException();
}

@Test
@WithMockUser(roles = "USER")
void shouldDenyUserFromDeletingUser() {
  assertThatThrownBy(() -> service.deleteUser(1L))
    .isInstanceOf(AccessDeniedException.class);
}
式ベースのセキュリティテスト
@PreAuthorize("#userId == authentication.principal.id")
public UserProfile getUserProfile(Long userId) {
  // get profile
}

// For custom principal properties, use @WithUserDetails with a custom UserDetailsService
@Test
@WithUserDetails("alice")
void shouldAllowUserToAccessOwnProfile() {
  assertThatCode(() -> service.getUserProfile(1L))
    .doesNotThrowAnyException();
}

検証のヒント:セキュリティテストが予期せず成功する場合は、テスト設定で @EnableMethodSecurity が有効になっていることを確認してください。このアノテーションがないと、すべての @PreAuthorize チェックが気付かれないまま回避されます。

基本的なパターンについては references/basic-testing.md、複雑な式やカスタム評価器については references/advanced-authorization.md を参照してください。

ベストプラクティス

  1. 認証済みユーザーのコンテキストを設定するには @WithMockUser を使用する
  2. 各セキュリティルールについて 許可と拒否の両方のケースをテストする
  3. ロールに基づく判断を確認するために 異なるロールでテストする
  4. 式ベースのセキュリティを網羅的にテストする
  5. 外部依存関係(権限評価器など)をモックする
  6. 認証済みアクセスとは分けて 匿名アクセスをテストする
  7. メソッドレベルセキュリティの設定には @EnableGlobalMethodSecurity を使用する

よくある落とし穴

  • テスト設定でメソッドセキュリティを有効にし忘れる
  • 許可と拒否の両方のシナリオをテストしない
  • 認可ロジックではなく、フレームワークのコードをテストする
  • テストで null 認証を処理しない
  • 認証テストと認可テストを不必要に混在させる

制約と注意事項

  • メソッドセキュリティにはプロキシが必要です:@PreAuthorize はプロキシを介して動作します。メソッドを直接呼び出すとセキュリティが回避されます
  • @EnableGlobalMethodSecurity:@PreAuthorize と @Secured を動作させるには有効にする必要があります
  • ロールのプレフィックス:Spring は自動的に「ROLE_」プレフィックスを追加します。hasRole('ROLE_ADMIN') ではなく hasRole('ADMIN') を使用します
  • 認証コンテキスト:セキュリティコンテキストはスレッドローカルです。非同期テストでは注意してください
  • @WithMockUser の制限:単純な Authentication を作成します。複雑な認証シナリオにはカスタム設定が必要です
  • SpEL 式:@PreAuthorize 内の複雑な SpEL はデバッグが難しい場合があります。十分にテストしてください
  • パフォーマンスへの影響:メソッドセキュリティはオーバーヘッドを追加します。レイヤーの境界でのセキュリティも検討してください

参考資料

セットアップと設定
テストパターン
高度なトピック
完全な例

コメント