spring-boot-security-jwt
Spring Boot 3.5.x向けに、JJWTを使用したトークン生成、Bearer/Cookie認証、データベース/OAuth2連携、Spring Security 6.xを活用したRBAC/パーミッションベースのアクセス制御など、JWT認証・認可の実装パターンを提供します。Spring Bootアプリケーションで認証や認可を実装する際に使用してください。
description の原文を見る
Provides JWT authentication and authorization patterns for Spring Boot 3.5.x covering token generation with JJWT, Bearer/cookie authentication, database/OAuth2 integration, and RBAC/permission-based access control using Spring Security 6.x. Use when implementing authentication or authorization in Spring Boot applications.
SKILL.md 本文
Spring Boot JWT Security
Spring Security 6.x と JJWT を使用した Spring Boot 3.5.x 向けの JWT 認証と認可パターン。トークン生成、検証、リフレッシュ戦略、RBAC/ABAC、および OAuth2 統合をカバーしています。
概要
このスキルは Spring Boot アプリケーションにおけるステートレス JWT 認証の実装パターンを提供します。JJWT 0.12.6 によるトークン生成、Bearer/Cookie ベースの認証、リフレッシュトークンローテーション、および @PreAuthorize 式によるメソッドレベルの認可を含む完全な認証フロー全体をカバーしています。
主な機能:
- 設定可能な有効期限を持つアクセストークンとリフレッシュトークンの生成
- Bearer トークンと HttpOnly Cookie の認証戦略
- Spring Data JPA と OAuth2 プロバイダーの統合
- ロール/パーミッションベースの
@PreAuthorizeルールによる RBAC - ログアウト/ローテーション用のトークン無効化とブラックリスト化
使用時機
以下のユーザーリクエストに関連する場合に有効化します:
- 「JWT 認証を実装する」、「トークンで REST API をセキュアにする」
- 「Spring Security 6.x 設定」、「SecurityFilterChain セットアップ」
- 「ロールベースアクセス制御」、「RBAC」、
@PreAuthorize - 「リフレッシュトークン」、「トークンローテーション」、「トークン無効化」
- 「OAuth2 統合」、「ソーシャルログイン」、「Google/GitHub 認証」
- 「ステートレス認証」、「SPA バックエンドセキュリティ」
- 「JWT フィルター」、「OncePerRequestFilter」、「Bearer トークン」
- 「Cookie ベースの JWT」、「HttpOnly Cookie」
- 「パーミッションベースのアクセス制御」、「カスタム PermissionEvaluator」
クイックリファレンス
依存関係 (JJWT 0.12.6)
| アーティファクト | スコープ |
|---|---|
spring-boot-starter-security | compile |
spring-boot-starter-oauth2-resource-server | compile |
io.jsonwebtoken:jjwt-api:0.12.6 | compile |
io.jsonwebtoken:jjwt-impl:0.12.6 | runtime |
io.jsonwebtoken:jjwt-jackson:0.12.6 | runtime |
spring-security-test | test |
Maven および Gradle のスニペットは references/jwt-quick-reference.md を参照してください。
主要な設定プロパティ
| プロパティ | 例 | 注記 |
|---|---|---|
jwt.secret | ${JWT_SECRET} | 最小 256 ビット、ハードコード禁止 |
jwt.access-token-expiration | 900000 | 15 分(ミリ秒単位) |
jwt.refresh-token-expiration | 604800000 | 7 日(ミリ秒単位) |
jwt.issuer | my-app | すべてのトークンで検証 |
jwt.cookie-name | jwt-token | Cookie ベース認証用 |
jwt.cookie-http-only | true | 本番環境では必ず true |
jwt.cookie-secure | true | HTTPS では必ず true |
認可アノテーション
| アノテーション | 例 |
|---|---|
@PreAuthorize("hasRole('ADMIN')") | ロールチェック |
@PreAuthorize("hasAuthority('USER_READ')") | パーミッションチェック |
@PreAuthorize("hasPermission(#id, 'Doc', 'READ')") | ドメインオブジェクトチェック |
@PreAuthorize("@myService.canAccess(#id)") | Spring Bean チェック |
手順
ステップ 1 — 依存関係を追加
spring-boot-starter-security、spring-boot-starter-oauth2-resource-server、および 3 つの JJWT アーティファクトをビルドファイルに含めます。正確な Maven/Gradle スニペットは references/jwt-quick-reference.md を参照してください。
ステップ 2 — application.yml を設定
jwt:
secret: ${JWT_SECRET:change-me-min-32-chars-in-production}
access-token-expiration: 900000
refresh-token-expiration: 604800000
issuer: my-app
cookie-name: jwt-token
cookie-http-only: true
cookie-secure: false # 本番環境では true
完全なプロパティリファレンスは references/jwt-complete-configuration.md を参照してください。
ステップ 3 — JwtService を実装
コア操作: アクセストークン生成、リフレッシュトークン生成、ユーザー名抽出、トークン検証。
@Service
public class JwtService {
public String generateAccessToken(UserDetails userDetails) {
return Jwts.builder()
.subject(userDetails.getUsername())
.issuer(issuer)
.issuedAt(new Date())
.expiration(new Date(System.currentTimeMillis() + accessTokenExpiration))
.claim("authorities", getAuthorities(userDetails))
.signWith(getSigningKey())
.compact();
}
public boolean isTokenValid(String token, UserDetails userDetails) {
try {
String username = extractUsername(token);
return username.equals(userDetails.getUsername()) && !isTokenExpired(token);
} catch (JwtException e) {
return false;
}
}
}
キー管理とクレイム抽出を含む完全な JwtService は references/jwt-complete-configuration.md を参照してください。
ステップ 4 — JwtAuthenticationFilter を作成
OncePerRequestFilter を拡張して、Authorization: Bearer ヘッダー(または HttpOnly Cookie)から JWT を抽出し、それを検証して SecurityContext を設定します。
@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response, FilterChain chain)
throws ServletException, IOException {
String authHeader = request.getHeader("Authorization");
if (authHeader == null || !authHeader.startsWith("Bearer ")) {
chain.doFilter(request, response);
return;
}
String jwt = authHeader.substring(7);
String username = jwtService.extractUsername(jwt);
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
if (jwtService.isTokenValid(jwt, userDetails)) {
UsernamePasswordAuthenticationToken authToken =
new UsernamePasswordAuthenticationToken(
userDetails, null, userDetails.getAuthorities());
authToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authToken);
}
}
chain.doFilter(request, response);
}
}
Cookie ベースのバリアントは references/configuration.md を参照してください。
ステップ 5 — SecurityFilterChain を設定
@Configuration
@EnableWebSecurity
@EnableMethodSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
return http
.csrf(AbstractHttpConfigurer::disable)
.sessionManagement(s -> s.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/auth/**", "/swagger-ui/**").permitAll()
.anyRequest().authenticated()
)
.authenticationProvider(authenticationProvider)
.addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class)
.build();
}
}
CORS、ログアウトハンドラー、OAuth2 ログイン統合については references/jwt-complete-configuration.md を参照してください。
ステップ 6 — 認証エンドポイントを作成
@RestController 経由で /register、/authenticate、/refresh、/logout を公開します。レスポンスボディに accessToken + refreshToken を返します(オプションで HttpOnly Cookie を設定)。
完全な AuthenticationController と AuthenticationService は references/examples.md を参照してください。
ステップ 7 — リフレッシュトークン戦略を実装
リフレッシュトークンをデータベースに user_id、expiry_date、revoked、expired カラムとともに保存します。/refresh では、保存されたトークンを検証し、それを無効化して、新しいペアを発行します(トークンローテーション)。
RefreshToken エンティティ、ローテーションロジック、Redis ベースのブラックリスト化については references/token-management.md を参照してください。
ステップ 8 — 認可ルールを追加
細粒度の制御のために @EnableMethodSecurity と @PreAuthorize アノテーションを使用します:
@PreAuthorize("hasRole('ADMIN')")
public Page<UserResponse> getAllUsers(Pageable pageable) { ... }
@PreAuthorize("hasPermission(#documentId, 'Document', 'READ')")
public Document getDocument(Long documentId) { ... }
RBAC エンティティモデル、PermissionEvaluator、ABAC パターンについては references/authorization-patterns.md を参照してください。
ステップ 9 — セキュリティテストを書く
@SpringBootTest
@AutoConfigureMockMvc
class AuthControllerTest {
@Test
void shouldDenyAccessWithoutToken() throws Exception {
mockMvc.perform(get("/api/orders"))
.andExpect(status().isUnauthorized());
}
@Test
@WithMockUser(roles = "ADMIN")
void shouldAllowAdminAccess() throws Exception {
mockMvc.perform(get("/api/admin/users"))
.andExpect(status().isOk());
}
}
完全なテストスイート、Testcontainers セットアップ、セキュリティテストチェックリストは references/testing.md および references/jwt-testing-guide.md を参照してください。
ベストプラクティス
トークンセキュリティ
- 最小 256 ビットの秘密鍵を使用 — 環境変数から読み込み、ハードコード禁止
- アクセストークンのライフタイムを短く設定(15 分); 長いセッション用にリフレッシュトークンを使用
- トークンローテーションを実装: 新しいリフレッシュトークンを発行する際に古いものを無効化
- ログアウト時のブラックリスト化のために
jti(JWT ID) クレイムを使用
Cookie vs Bearer ヘッダー
- ブラウザクライアントは HttpOnly Cookie を優先(XSS セーフ)
- モバイル/API クライアントには
Authorization: Bearerヘッダーを使用 - 本番環境で Cookie に
Secure、SameSite=LaxまたはStrictを設定
Spring Security 6.x
SecurityFilterChainBean を使用 —WebSecurityConfigurerAdapterを拡張しない- CSRF はステートレス API のみで無効化; セッションベースのフローでは有効に保つ
- 非推奨の
@EnableGlobalMethodSecurityの代わりに@EnableMethodSecurityを使用 issおよびaudクレイムを検証; 信頼できないイシュアーからのトークンを拒否
パフォーマンス
- DB ルックアップを回避するため
@CacheableでUserDetailsをキャッシュ - 署名キー導出をキャッシュ(リクエストごとに HMAC キーの再計算を回避)
- 大規模環境ではリフレッシュトークンストレージに Redis を使用
やってはいけないこと
- JWT クレイムに機密データ(パスワード、個人情報)を格納しない — クレイムは署名されているだけで暗号化されていない
- 無期限のトークンを発行しない
- 署名と有効期限を検証せずにトークンを受け入れない
- 環境間で署名鍵を共有しない
例
基本的な認証フロー
@RestController
@RequestMapping("/api/auth")
@RequiredArgsConstructor
public class AuthController {
private final AuthService authService;
@PostMapping("/authenticate")
public ResponseEntity<AuthResponse> authenticate(
@RequestBody LoginRequest request) {
return ResponseEntity.ok(authService.authenticate(request));
}
@PostMapping("/refresh")
public ResponseEntity<AuthResponse> refresh(@RequestBody RefreshRequest request) {
return ResponseEntity.ok(authService.refreshToken(request.refreshToken()));
}
@PostMapping("/logout")
public ResponseEntity<Void> logout() {
authService.logout();
return ResponseEntity.ok().build();
}
}
コントローラーメソッドでの JWT 認可
@RestController
@RequestMapping("/api/admin")
@PreAuthorize("hasRole('ADMIN')")
public class AdminController {
@GetMapping("/users")
public ResponseEntity<List<UserResponse>> getAllUsers() {
return ResponseEntity.ok(adminService.getAllUsers());
}
}
完全なエンティティモデルとサービス実装は references/examples.md を参照してください。
参考資料
| ファイル | 内容 |
|---|---|
references/jwt-quick-reference.md | 依存関係、最小限のサービス、一般的なパターン |
references/jwt-complete-configuration.md | 完全な設定: プロパティ、SecurityFilterChain、JwtService、OAuth2 RS |
references/configuration.md | JWT 設定 Bean、CORS、CSRF、エラーハンドリング、セッションオプション |
references/examples.md | 完全なアプリケーションセットアップ: コントローラー、サービス、エンティティ |
references/authorization-patterns.md | RBAC/ABAC エンティティモデル、PermissionEvaluator、SpEL 式 |
references/token-management.md | リフレッシュトークンエンティティ、ローテーション、Redis によるブラックリスト化 |
references/testing.md | ユニットテストと MockMvc テスト、テストユーティリティ |
references/jwt-testing-guide.md | Testcontainers、負荷テスト、セキュリティテストチェックリスト |
references/security-hardening.md | セキュリティヘッダー、HSTS、レート制限、監査ログ |
references/performance-optimization.md | Caffeine キャッシュ設定、非同期検証、コネクションプーリング |
references/oauth2-integration.md | Google/GitHub OAuth2 ログイン、OAuth2UserService |
references/microservices-security.md | サービス間 JWT 伝播、リソースサーバー設定 |
references/migration-spring-security-6x.md | Spring Security 5.x からのマイグレーション |
references/troubleshooting.md | 一般的なエラー、デバッグのヒント |
制約と警告
セキュリティ上の制約
- JWT トークンは署名されていますが暗号化されていません — クレイムに機密データを含めない
- トークンを信頼する前に常に
exp、iss、audクレイムを検証 - 署名鍵は最低 256 ビット以上である必要があります; 本番環境では弱い鍵を使用しない
- 秘密を環境変数またはセキュアなボルトから読み込み、設定ファイルから読み込まない
- SameSite Cookie 属性は Cookie ベースのフローにおける CSRF 保護に不可欠
Spring Security 6.x 上の制約
WebSecurityConfigurerAdapterは削除されました —SecurityFilterChainBean のみを使用@EnableGlobalMethodSecurityは非推奨 —@EnableMethodSecurityを使用- Lambda DSL は
HttpSecurity設定に必須(メソッドチェーンなし) WebSecurityConfigurerAdapter.order()は@Configurationクラスの@Orderに置き換わり
トークン上の制約
- アクセストークンはセキュリティのため 5 ~ 15 分で有効期限切れにすべき
- リフレッシュトークンはサーバーサイド(DB または Redis)に保存すべき、localStorage には保存しない
- ログアウト時の即時無効化のためトークンブラックリスト化を実装
- トークンブラックリスト化が機能するため
jtiクレイムは必須
関連スキル
spring-boot-dependency-injection— 全体で使用されるコンストラクタインジェクションパターンspring-boot-rest-api-standards— REST API セキュリティパターンとエラーハンドリングunit-test-security-authorization— Spring Security 設定のテストspring-data-jpa— User エンティティとリポジトリパターンspring-boot-actuator— セキュリティ監視とヘルスチェックエンドポイント
ライセンス: MIT(寛容ライセンスのため全文を引用しています) · 原本リポジトリ
詳細情報
- 作者
- giuseppe-trisciuoglio
- ライセンス
- MIT
- 最終更新
- 不明
Source: https://github.com/giuseppe-trisciuoglio/developer-kit / ライセンス: MIT
関連スキル
secure-code-guardian
認証・認可の実装、ユーザー入力の保護、OWASP Top 10の脆弱性対策が必要な場合に使用します。bcrypt/argon2によるパスワードハッシング、パラメータ化ステートメントによるSQLインジェクション対策、CORS/CSPヘッダーの設定、Zodによる入力検証、JWTトークンの構築などのカスタムセキュリティ実装に対応します。認証、認可、入力検証、暗号化、OWASP Top 10対策、セッション管理、セキュリティ強化全般で活用できます。ただし、構築済みのOAuth/SSO統合や単独のセキュリティ監査が必要な場合は、より特化したスキルの検討をお勧めします。
claude-authenticity
APIエンドポイントが本物のClaudeによって支えられているか(ラッパーやプロキシ、偽装ではないか)を、claude-verifyプロジェクトを模した9つの重み付きルールベースチェックで検証できます。また、Claudeの正体を上書きしているプロバイダーから注入されたシステムプロンプトも抽出します。完全に自己完結しており、httpx以外の追加パッケージは不要です。Claude APIキーまたはエンドポイントを検証したい場合、サードパーティのClaudeサービスが本物か確認したい場合、APIプロバイダーのClaude正当性を監査したい場合、複数モデルを並行してテストしたい場合、またはプロバイダーが注入したシステムプロンプトを特定したい場合に使用できます。
anth-security-basics
Anthropic Claude APIのセキュリティベストプラクティスを適用し、キー管理、入力値の検証、プロンプトインジェクション対策を実施します。APIキーの保護、Claudeに送信する前のユーザー入力検証、コンテンツセーフティガードレールの実装が必要な場合に活用できます。「anthropic security」「claude api key security」「secure anthropic」「prompt injection defense」といったフレーズでトリガーされます。
x-ray
x-ray.mdプレ監査レポートを生成します。概要、強化された脅威モデル(プロトコルタイプのプロファイリング、Gitの重み付け攻撃面分析、時間軸リスク分析、コンポーザビリティ依存関係マッピング)、不変条件、統合、ドキュメント品質、テスト分析、開発者・Gitの履歴をカバーしています。「x-ray」「audit readiness」「readiness report」「pre-audit report」「prep this protocol」「protocol prep」「summarize this protocol」のキーワードで実行されます。
semgrep
Semgrepスタティック分析スキャンを実行し、カスタム検出ルールを作成します。Semgrepでのコードスキャン、セキュリティ脆弱性の検出、カスタムYAMLルールの作成、または特定のバグパターンの検出が必要な場合に使用します。重要:ユーザーが「バグをスキャンしたい」「コード品質を確認したい」「脆弱性を見つけたい」「スタティック分析」「セキュリティlint」「コード監査」または「コーディング標準を適用したい」と尋ねた場合も、Semgrepという名称を明記していなくても、このスキルを使用してください。Semgrepは30以上の言語に対応したパターンベースのコードスキャンに最適なツールです。
ghost-bits-cast-attack
Java「ゴーストビッツ」/キャストアタック プレイブック(Black Hat Asia 2026)。16ビット文字が8ビットバイトに暗黙的に縮小されるJavaサービスへの攻撃時に使用します。WAF/IDSを回避して、SQLインジェクション、デシリアライゼーション型RCE、ファイルアップロード(Webシェル)、パストトラバーサル、CRLF インジェクション、リクエストスマグリング、SMTPインジェクションを実行できます。Tomcat、Spring、Jetty、Undertow、Vert.x、Jackson、Fastjson、Apache Commons BCEL、Apache HttpClient、Angus Mail、JDK HttpServer、Lettuce、Jodd、XMLWriterに影響し、WAFバイパスにより多くの「パッチ済み」CVEを再度有効化します。