Spring BootとNext.jsを活用した多層セキュリティアーキテクチャの構築


# Spring BootとNext.jsを活用した多層セキュリティアーキテクチャの構築

---

現代のWebアプリケーション開発では、Spring BootとNext.jsの組み合わせが生産性とパフォーマンスの両面で大きなメリットをもたらしています。一方で、分散アーキテクチャ特有のセキュリティ課題に対処するためには、バックエンドとフロントエンドの両側面からしっかりと防御策を講じる必要があります。本報告では、OWASP Top 10で挙げられる主要な脆弱性に対応するための、体系的かつ実践的な対策戦略について明記いたしました。


## 全体の流れ

```mermaid
flowchart TD
    %% フロントエンド（Next.js）側
    subgraph FE [Next.js Frontend]
        A1[ユーザー操作]
        A2[Reactコンポーネント]
        A3[Next.js ミドルウェアCSP, HTTPヘッダー設定]
    end

    %% バックエンド（Spring Boot）側
    subgraph BE [Spring Boot REST API]
        B1[APIエンドポイント]
        B2[Spring SecurityJWT認証, RBAC]
        B3[ビジネスロジック]
        B4[データベースアクセス]
    end

    %% フローの定義
    A1 --> A2
    A2 --> A3
    A3 -- "HTTPリクエスト\n(認証情報含む)" --> B1
    B1 --> B2
    B2 -- "認証・認可チェック" --> B3
    B3 -- "DBクエリ/更新" --> B4
    B4 -- "結果返却" --> B3
    B3 -- "レスポンス生成" --> B2
    B2 -- "セキュリティ検証後" --> B1
    B1 -- "HTTPレスポンス" --> A3
    A3 --> A2

```

## 認証・認可機構の強化

### トークンベース認証の実装

JWT（JSON Web Tokens）を採用したステートレス認証をSpring Securityで実装する。アクセストークンの有効期間を15分に設定し、リフレッシュトークンによる更新メカニズムを組み込むことで、セッション固定化攻撃のリスクを低減する[^4][^12]。トークンの署名にはHMAC-SHA256アルゴリズムを適用し、秘密鍵は環境変数経由で注入する。

```java
@Bean
public JwtDecoder jwtDecoder() {
    return NimbusJwtDecoder.withSecretKey(new SecretKeySpec(
        Decoders.BASE64.decode(secretKey),
        SignatureAlgorithm.HS256.getJcaName()
    )).build();
}
```


### ロールベースアクセス制御（RBAC）

Spring Securityの`@PreAuthorize`アノテーションを活用し、メソッドレベルで細かな権限制御を実現する[^8][^15]。管理画面へのアクセスには`ADMIN`ロールを要求し、ユーザー固有のリソース操作時には`@PostAuthorize`で所有者確認を実施する。

```java
@PreAuthorize("hasRole('ADMIN')")
@PostMapping("/admin/users")
public ResponseEntity<User> createAdminUser(@RequestBody User user) {
    // 管理者ユーザー作成ロジック
}
```


## データ保護層の構築

### SQLインジェクション防御戦略

JPAのCriteria APIを採用し、型安全なクエリ構築を強制する[^13]。動的クエリが必要な場合でも、Hibernateの`@NamedQuery`で事前定義されたクエリのみを許可する。入力値検証にはJakarta Bean Validation 3.0を適用し、`@SafeHtml`アノテーションでHTMLタグの混入を防止する[^9]。

```java
@Entity
@NamedQuery(
    name = "User.findByEmail",
    query = "SELECT u FROM User u WHERE u.email = :email"
)
public class User {
    @SafeHtml
    private String email;
}
```


### セッション管理の最適化

Spring SessionでRedisクラスタをセッションストアとして構成し、セッションレプリケーションを実現する[^6][^10]。Cookie属性には`SameSite=Strict`、`HttpOnly`、`Secure`を設定し、クライアントサイドスクリプトからのアクセスを遮断する[^13]。セッションタイムアウトは15分に設定し、非活動時には自動的に無効化する。

```properties
server.servlet.session.timeout=900
server.servlet.session.cookie.http-only=true
server.servlet.session.cookie.secure=true
server.servlet.session.cookie.same-site=strict
```


## クライアントサイド保護機構

### Content Security Policy（CSP）の厳格化

Next.jsのミドルウェア層で動的にCSPヘッダーを生成し、信頼できるドメインのみにリソース読み込みを制限する[^3][^7][^14]。nonceベースのスクリプト実行ポリシーを採用し、インラインスクリプトの実行を完全に禁止する。

```typescript
export function middleware() {
    const nonce = Buffer.from(crypto.randomBytes(16)).toString('hex');
    const csp = `
        default-src 'self';
        script-src 'self' 'nonce-${nonce}';
        style-src 'self' 'unsafe-inline';
        img-src 'self' data:;
        connect-src 'self' api.example.com;
        frame-ancestors 'none';
    `.replace(/\s+/g, ' ');

    return NextResponse.next().headers.set('Content-Security-Policy', csp);
}
```


### XSS防御の多層化

ReactのJSXテンプレートにおける自動エスケープ機能を活用しつつ、DOMPurifyでクライアントサイドのサニタイズを二重に実施する[^7][^18]。危険なHTML挿入が必要な場合は、専用のサニタイズコンポーネントを経由させる。

```typescript
const SanitizedHTML = ({ content }: { content: string }) => {
    const clean = DOMPurify.sanitize(content);
    return <div dangerouslySetInnerHTML={{ __html: clean }} />;
};
```


## ネットワーク層の防御策

### CORSポリシーの厳密化

Spring Securityで許可するオリジンをNext.jsのデプロイドメインのみに制限し、プリフライトリクエストに対するキャッシュ時間を2分に設定する[^5][^9][^16]。認証が必要なエンドポイントには`Access-Control-Allow-Credentials: true`を設定し、資格情報の送信を明示的に許可する。

```java
@Bean
public CorsConfigurationSource corsConfigurationSource() {
    CorsConfiguration config = new CorsConfiguration();
    config.setAllowedOrigins(List.of("https://frontend.example.com"));
    config.setAllowedMethods(List.of("GET","POST"));
    config.setAllowCredentials(true);
    config.setMaxAge(120L);

    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    source.registerCorsConfiguration("/**", config);
    return source;
}
```


### HTTPヘッダーの強化

Next.js側で`X-Frame-Options: DENY`と`X-Content-Type-Options: nosniff`を設定し、MIMEタイプスニッフィングを防止する[^3][^7][^13]。HSTSポリシーを1年に設定し、HTTPS通信を強制する。

```typescript
export function middleware() {
    const headers = new Headers();
    headers.set('Strict-Transport-Security', 'max-age=31536000; includeSubDomains');
    headers.set('X-Content-Type-Options', 'nosniff');
    headers.set('X-Frame-Options', 'DENY');

    return NextResponse.next().headers(headers);
}
```


## 継続的セキュリティ監視

### 依存関係の脆弱性管理

GradleのDependency Checkプラグインを導入し、週次で依存ライブラリのスキャンを自動実行する[^1][^9]。検出された脆弱性はJIRAと連携し、48時間以内の対応を義務付ける。Spring Bootのバージョン管理にはRenovateBotを導入し、セキュリティパッチを自動適用する。

```groovy
plugins {
    id 'org.owasp.dependencycheck' version '8.2.1'
}

dependencyCheck {
    formats = ['HTML', 'JSON']
    failBuildOnCVSS = 7.0
    suppressionFile = 'config/dependency-suppressions.xml'
}
```


### 動的アプリケーションセキュリティテスト（DAST）

OWASP ZAPをCI/CDパイプラインに統合し、本番環境デプロイ前に自動スキャンを実施する[^9][^19]。検出された問題はゼロトラスト原則に基づき、重大度レベルに応じたエスカレーションプロセスを適用する。ペネトレーションテストは年4回実施し、第三者機関による客観的評価を受ける。

## インシデント対応体制

### リアルタイム監視システム

ELKスタック（Elasticsearch, Logstash, Kibana）を構築し、認証失敗ログや不審なリクエストパターンを検知する[^13][^19]。異常検知には機械学習モデルを導入し、通常と異なるアクセスパターンを検出した場合、自動でIPブロックを実施する。

```java
@Slf4j
@Aspect
@Component
public class SecurityMonitoringAspect {
    @AfterThrowing(pointcut = "execution(* org.springframework.security.authentication.ProviderManager.authenticate(..))", throwing = "ex")
    public void logAuthenticationFailure(AuthenticationException ex) {
        log.warn("Authentication failed: {}", ex.getMessage());
        // アラート通知システムへの連携
    }
}
```


### フォレンジック準備体制

すべてのリクエストに相関IDを付与し、分散トレーシングシステムでリクエストフローを追跡可能にする[^12][^16]。監査ログはWORM（Write Once Read Many）ストレージに保存し、改ざん検知機能を備える。インシデント発生時には、60分以内に初期対応チームが招集されるEscalation Policyを確立する。

## 結論

Spring BootとNext.jsを組み合わせたアプリケーションのセキュリティは、多層防御の原則に基づき、各レイヤーで独立した保護機構を構築することが重要である。認証・認可機構の強化から始め、データ保護層、クライアントサイド保護、ネットワーク防御を体系的に整備する。継続的な監視と自動化された脆弱性管理を組み合わせることで、進化する脅威プロファイルに対応できる。特に、マイクロサービスアーキテクチャでは、サービス間通信のセキュリティをJWTの署名検証と暗号化で担保することが不可欠となる。今後の課題として、量子コンピュータ耐性を持つ認証方式の検討と、AIを活用した異常検知システムの高度化が挙げられる。

<div style="text-align: center">⁂</div>

[^1]: https://www.conoris.jp/column/vulnerability-spring-boot

[^2]: https://star-school.jp/spring/130

[^3]: http://izanami.dev/post/b10d2c64-159c-4a02-9ead-a808a28c551a

[^4]: https://qiita.com/jtths474/items/9fa1fb8d42896d91e7e4

[^5]: https://qiita.com/RYA234/items/bef61d03304f095a3791

[^6]: https://kojinjigyou.org/72523/

[^7]: https://qiita.com/JZ8xNeXY/items/7337d9e7e04b4ae121a7

[^8]: https://qiita.com/homes31285/items/022bcd723212a7ad9068

[^9]: https://tecnohakase.one/1002/

[^10]: https://colors.ambl.co.jp/spring-security-training/

[^11]: https://zenn.dev/yutoo89/articles/d1ed72b821b2c0

[^12]: https://zenn.dev/kiyotatakeshi/articles/d12a850f232d71

[^13]: https://www.docswell.com/s/MasatoshiTada/ZYWP29-spring-boot-security

[^14]: https://www.hexabase.com/column/Frontend_security

[^15]: https://spring.pleiades.io/spring-security/reference/servlet/authorization/architecture.html

[^16]: https://www.issoh.co.jp/tech/details/1542/

[^17]: https://www.tsuzukanai.com/spring-boots-save-session/

[^18]: https://www.proofpoint.com/jp/threat-reference/cross-site-scripting-xss

[^19]: https://dev.classmethod.jp/articles/spring-boot-web-security/

[^20]: https://zenn.dev/angelica/books/52be1e365c61ea/viewer/f0683a

[^21]: https://i-ssue.com/topics/4epi6mi1wkfb20qc1256cl

[^22]: https://codezine.jp/article/detail/11703

[^23]: https://note.com/commonerd/n/n5a847f2e5029

[^24]: https://kojinjigyou.org/78855/

[^25]: https://macchinetta.github.io/server-guideline/1.8.1.RELEASE/ja/Introduction/ChangeLog.html

[^26]: https://security.sios.jp/vulnerability/spring4shell-vulnerability-20220401/

[^27]: https://freelance.techcareer.jp/projects/detail/29206/

[^28]: https://www.hitachi-solutions.co.jp/-/media/Project/DefaultSite/Products/pdf/c/coverity_static-analysis_pdf.ashx

[^29]: https://www.seplus.jp/dokushuzemi/blog/2018/08/entry_javascript.html

[^30]: https://remogu.jp

[^31]: https://trends.codecamp.jp/blogs/media/news264

[^32]: https://qiita.com/dexcter/items/ca75cf0acf4121b7f366

[^33]: https://note.com/sudatakashi/n/n66f522f9ba7c

[^34]: https://qiita.com/tamura__246/items/85c61dc06695ca1da89a

[^35]: https://www.aeyescan.jp/blog/spring_framework_vulnerabilities/

[^36]: https://zenn.dev/mumin0101/articles/ced5ea63442c61

[^37]: https://avocado-system.com/2023/05/03/【mybatis】sqlインジェクション対策/

[^38]: https://zenn.dev/kumao/scraps/5394faef6d5521

[^39]: https://b.hatena.ne.jp/entry/s/hiro-tracks.net/jdbctemp-sql-injection/

[^40]: https://terasolunaorg.github.io/guideline/5.0.0.RELEASE/ja/ArchitectureInDetail/DataAccessMyBatis3.html

[^41]: https://qiita.com/EasyCoder/items/78aea71564987faee7f3

[^42]: https://spring.pleiades.io/spring-security/reference/servlet/authentication/session-management.html

[^43]: https://www.webpilot.ai/writeDetail/096aee94-a238-4971-8b30-bad924358e2e

[^44]: https://b1san-blog.com/post/spring/spring-session/

[^45]: https://terasolunaorg.github.io/guideline/5.1.0.RELEASE/ja/ArchitectureInDetail/SessionManagement.html

[^46]: https://www.kimullaa.com/posts/201603051542/

[^47]: https://speakerdeck.com/kazuhiro1982/setusiyondetafalseguan-li-nispring-sessionwoli-yong-suru

[^48]: https://www.youtube.com/watch?v=oW_rPUKPY7A

[^49]: https://www.commte.co.jp/learn-nextjs/XSS

[^50]: https://zenn.dev/monicle/articles/aee4871b288264

[^51]: https://www.fullstackchannel.com/questions/104

[^52]: https://jvndb.jvn.jp/ja/contents/2021/JVNDB-2021-010977.html

[^53]: https://azukiazusa.dev/blog/react-javascript-xss

[^54]: https://macchinetta.github.io/server-guideline-thymeleaf/1.9.1.RELEASE/ja/Security/XSS.html

[^55]: https://yamory.io/blog/about-xss

[^56]: https://terasolunaorg.github.io/guideline/5.2.1.RELEASE/ja/Security/XSS.html

[^57]: https://www.ipa.go.jp/security/vuln/websecurity/cross-site-scripting.html

[^58]: https://www.f5.com/ja_jp/glossary/cross-site-scripting

[^59]: https://www.crowdstrike.com/ja-jp/cybersecurity-101/cyberattacks/cross-site-scripting-xss/

[^60]: https://v0.dev/chat/next-js-shadcn-ui-fyfkrxg9v1X

[^61]: https://x.com/Sicut_study/status/1888906005704245334

[^62]: https://cs27.org/wiki/kobespiral2021/

[^63]: https://www.issoh.co.jp/tech/details/2467/

[^64]: https://www.tsuzukanai.com/spring-boot-spring-security-introduction/

[^65]: https://www.ios-net.co.jp/blog/20240117-2019/

[^66]: https://terasolunaorg.github.io/guideline/5.6.0.RELEASE/ja/Security/SpringSecurity.html

[^67]: https://note.com/turtle_aware137/n/n87601df4f013

[^68]: https://www.trainocate.co.jp/reference/course_details.aspx?code=JAC0170R

[^69]: https://zenn.dev/waka_morita/articles/ec561dc24e0ab2

[^70]: https://engineer-style.jp/articles/9702

[^71]: https://note.com/webnote32/n/n759238dd6030

[^72]: https://qiita.com/hiroe-mkk/items/91c7a95a721400aac77a

[^73]: https://www.techmatrix.co.jp/product/jtest/security/injection.html

[^74]: https://hiro-tracks.net/jdbctemp-sql-injection/

[^75]: https://hack-lab-256.com/spring-boot-mybatis-sql-injection/1213/

[^76]: https://proengineer.internous.co.jp/content/columnfeature/20309

[^77]: https://terasolunaorg.github.io/guideline/5.2.1.RELEASE/ja/Security/SessionManagement.html

[^78]: https://qiita.com/reoring/items/7b5a48022d5918a16ac5

[^79]: https://www.kimullaa.com/posts/201605080505/

[^80]: https://note.com/webnote32/n/n6d63ebd7afb4