0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Spring Securityについてなんとなく分かる記事

Last updated at Posted at 2025-10-17

はじめに

Springbootを使ってるけど、SpringSecurityっていったいなんなの?設定は行ったけど、裏でどんな風に動いてるの?というのをまとめてみたいと思います。

参考
SpringSecurity公式ドキュメント
プロになるためのSpring入門ーーゼロからの開発力養成講座

Spring Securityとは

公式ドキュメントより

Spring Security は、認証、認可、一般的な攻撃に対する保護を提供するフレームワークです。命令型およびリアクティブ両方のアプリケーションに対するファーストクラスのサポートにより、Spring ベースのアプリケーションを保護するためのデファクトスタンダードとなっています。

つまり、なにかすごいことをしてくれているフレームワークです。。。

もう少し簡単に要約すると、

  • Spring Security(スプリング・セキュリティ)は、JavaのSpringベースのアプリケーションに対して、認証(Authentication)と認可(Authorization)をはじめとする、様々なセキュリティ機能を提供するフレームワークです。

つまり

Spring Securityとは「門番システム」です
Spring Securityの役割は、Webアプリケーションを「安全な建物」にするための「門番(セキュリティシステム)」を提供することです。

主な機能

Spring Securityの主な機能は以下の2点に集約されます。

1.認証 (Authentication)

  • ユーザーが「誰であるか」を確認するプロセスです。

  • ユーザー名とパスワードの検証などを行い、正当なユーザーであることを確認します。(ユーザーが誰か、身分証で確認する)

  • 様々な認証方法(フォーム認証、LDAP、OAuth 2.0など)に対応しています

2. 認可 (Authorization)

  • 認証されたユーザーが「何にアクセスする権限を持っているか」を制御するプロセスです。

  • 特定のURLパス、メソッド、またはリソースへのアクセスを、ユーザーの役割(ロール)や権限に基づいて許可または拒否します。(ユーザーがどの部屋に入る許可を持っているか確認する。)

その他のセキュリティ対策

認証・認可の他にも、Webアプリケーションの一般的な脆弱性から保護するための機能を提供します。

  • CSRF(クロスサイトリクエストフォージェリ)対策

  • セッション固定攻撃対策

  • セキュリティヘッダーの出力(例: X-Frame-Options, HSTS

仕組みの概要

Spring Securityは、Webアプリケーションへのリクエストを処理する過程で、サーブレットフィルターの仕組みを利用してセキュリティ機能を実現しています。これにより、アプリケーションのビジネスロジックを変更することなく、宣言的にセキュリティルールを適用し、柔軟かつ拡張性の高いセキュリティ対策を実装できます。

仕組みは少しだけわかったけど、実際Spring Securityを動かすためにはどうすればいいの?専用のコントローラとかいるの?

ログイン認証を動かすために自分で決められたコントローラを作成してそこに飛ばす必要はありません。

Spring Securityを使う場合、通常は特定の条件を満たすHTMLフォーム設定を行うだけで、Spring Securityの内部フィルターが自動的にリクエストを処理し、認証ロジックを実行します

Spring Securityでのログイン認証の動作

ログイン認証を機能させるために、Webアプリケーション側で必要なことは主に以下の3点です。

1. ログインフォームの作成 (HTML)

Spring Securityのデフォルト設定を利用する場合、ログインフォームのHTMLは以下のルールに従って作成する必要があります。

  • アクションURL:/login (POSTメソッド)
    このURLにフォームを送信すると、Spring Securityの認証フィルターが自動的にリクエストをキャッチします。自分で/loginに対応するコントローラを定義する必要はありません。

  • ユーザー名フィールド:username
    ユーザー名(ID)を入力する要素のname属性をusernameにする必要があります。

  • パスワードフィールド:password
    パスワードを入力する<input>要素のname属性をpasswordにする必要があります。

HTMLフォームの例

<form method="POST" action="/login">
    <label for="username">ユーザー名:</label>
    <input type="text" id="username" name="username"><br>
    
    <label for="password">パスワード:</label>
    <input type="password" id="password" name="password"><br>
    
    <button type="submit">ログイン</button>
</form>

2. 認証ロジックの実装 (UserDetailsService)

フォームからの入力(ユーザー名)を受け取り、データベースからユーザー情報とパスワードを取得して、Spring Securityに渡すためのUserDetailsServiceの実装が必要です。

3. Spring Securityの設定 (SecurityFilterChain)

Spring Securityの設定クラス(SecurityConfigなど)で、フォームログインを有効にする設定を記述します。

// Spring Boot 3 以降の簡潔な設定例
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    http
        // 認可設定(アクセス制限)
        // ...
        
        // フォームログインを有効化(デフォルト設定を使用)
        .formLogin(Customizer.withDefaults()); // ← これだけでSpring Securityがログインフォーム処理を制御します。
        
    return http.build();
}

この設定を行うだけで、Spring Securityの内部にあるUsernamePasswordAuthenticationFilterというフィルターが/loginへのPOSTリクエストを自動的にインターセプトし、認証処理を実行します。そのため、専用のログイン処理コントローラを作る必要がありません。DI注入の技術を使用して、内部的に認証を行ってくれています。
Spring FrameworkのDIコンテナってなに?メリットは?

具体的な仕組み

Spring Securityの全ての機能は、「サーブレットフィルター」という仕組みで動いています。クライアントからのリクエストがWebアプリケーションの処理にたどり着く前に、たくさんのセキュリティの関所(フィルター)を順番に通過します。この関所の連なりをフィルターチェーンと呼びます

1. フィルターチェーンの図解

クライアントからのリクエストは、まずSpring Securityの多数のフィルターを順番に通過します。

image.png
特に重要なフィルターが、認証を行うフィルターと、認可を行うフィルターです。

image.png

リクエストは、まず認証フィルターで「誰か」を確認され、次に認可フィルターで「アクセス権があるか」を確認されてから、ようやくビジネスロジック(Controller)に到達します。

2. 認証の仕組みとコード(誰であるかの証明) (UserDetailsService)

認証の裏側の流れ(UserDetailsServiceの役割)

認証は、主にユーザー情報を取得するUserDetailsServiceというインターフェースを実装して行います

ログイン処理が実行されると、Spring Securityは以下の裏側の動きでユーザーを認証します。

  1. リクエストキャッチ: UsernamePasswordAuthenticationFilterが、フォームから送信されたIDとパスワードをキャッチします。

  2. 情報取得の依頼: フィルターは、UserDetailsServiceというコンポーネントに「このIDのユーザー情報をデータベースから取ってきて」と依頼します。

  3. 情報取得と返却: あなたが実装したUserDetailsServiceDBなどを参照し、ユーザーの情報(ID、ハッシュ化されたパスワード、権限)を返します。
    (UserDetailsServiceUserDetailsオブジェクトを返した後、裏側では以下の手順で「認証」が完了します)

  4. パスワード比較: フィルターは、入力されたパスワードと、DBから取得したパスワードを比較し、一致すれば認証成功となります。
    (UserDetailsServiceは、Spring Security内部のDaoAuthenticationProviderというコンポーネントに呼び出されています。このプロバイダーが、実際の認証(パスワードの比較)を行います。)

認証に必要なコード:UserDetailsServiceの実装

データベースやインメモリからユーザー情報を取得する役割を担います

@Service
public class CustomUserDetailsService implements UserDetailsService {
    // ユーザー情報(実際はDBから取得する)
    private final Map<String, String> users = Map.of(
        "taro", "{bcrypt}$2a$10$wTf7L...", // DBに保存されているハッシュ化されたパスワード
        "jiro", "{bcrypt}$2a$10$xyz4V..."  // bcrypt方式でエンコードされていることを示すプレフィックス
    );

    /**
     * ログインIDを元にユーザー情報を取得し、UserDetailsオブジェクトを返却する
     */
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        if (!users.containsKey(username)) {
            // ユーザーが見つからなければ例外をスロー
            throw new UsernameNotFoundException("ユーザー名が見つかりません: " + username);
        }

        // 取得した情報からUserDetailsオブジェクトを生成
        return User.withUsername(username)
                   .password(users.get(username))
                   .roles(getRoles(username)) // ロール(権限)を設定
                   .build();
    }
    
    // ユーザー名に対応するロールを返す(ここでは例としてハードコード)
    private String[] getRoles(String username) {
        if ("taro".equals(username)) {
            return new String[]{"ADMIN", "USER"};
        } else {
            return new String[]{"USER"};
        }
    }
}

認証済みオブジェクトの生成

認証プロバイダーは、認証が成功すると、以下の情報を含むAuthenticationというオブジェクトを生成します。

  1. プリンシパル (Principal): 認証済みのユーザー情報
  2. 権限 (Authorities): getAuthorities()から取得したロール(ROLE_ADMINなど)。
  3. 認証済みフラグ: isAuthenticated()trueになります。

セキュリティコンテキストへの保存

最後に、認証プロバイダーはこのAuthenticationオブジェクトをSecurityContextHolderという静的な場所に保存します。
SecurityContextHolder→SecurityContext→Authentication Object (認証済み)

このSecurityContextHolderに認証情報が保存されることで、その後の全てのリクエストで、Spring Securityは「このユーザーはログイン済みであり、ROLE_ADMINの権限を持っている」ことを迅速に確認できるようになります。

認可の仕組みとコード(何ができるかの制限)(設定)

認可の裏側の流れ(FilterSecurityInterceptorの役割)

認証が成功した後、ユーザーが特定のURLにアクセスしようとすると、以下の裏側の動きでアクセスが許可されるかがチェックされます。

  1. 権限チェックの実行: フィルターチェーンの終盤にあるFilterSecurityInterceptor(認可フィルター)が起動します。

  2. 設定を参照: 認可フィルターは、あなたが定義したSpring Securityの設定(SecurityFilterChain)を参照します。

  3. アクセス可否の判断: 「このURLにアクセスするには、ADMINというロールが必要だ」という設定と、ユーザーが持っているロールを照合します。

    • ロールを持っていれば → アクセス許可(アプリケーション本体へ処理が渡る)

    • ロールを持っていなければ → アクセス拒否(403 Forbiddenエラーを返す)

認可に必要なコード:SecurityFilterChainの設定

どのURLにどのようなアクセス権限(ロール)が必要かを定義します。

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            // 1. 認可リクエストの設定
            .authorizeHttpRequests(authorize -> authorize
                // /admin/以下のURLへのアクセスは、"ADMIN" ロールを持つユーザーのみ許可
                .requestMatchers("/admin/**").hasRole("ADMIN")
                
                // /user/以下のURLへのアクセスは、"USER" ロールを持つユーザーのみ許可
                .requestMatchers("/user/**").hasRole("USER")
                
                // /public/とトップページ("/")は、誰でもアクセスを許可 (permitAll)
                .requestMatchers("/", "/public/**").permitAll()
                
                // それ以外の全てのリクエストは、認証済みであること(ログイン済み)を要求
                .anyRequest().authenticated()
            )
            
            // 2. ログインフォームの設定 (デフォルトのログインページを使用)
            .formLogin(Customizer.withDefaults())
            
            // 3. ログアウトの設定
            .logout(logout -> logout
                .logoutSuccessUrl("/") // ログアウト成功後に遷移するページ
                .permitAll()
            );

        return http.build();
    }
}

補足: 役割 (Role) について
Spring Securityでは、アクセス権限を管理するためにロール(役割)という概念を使います。上記の例で、hasRole("ADMIN")と設定した場合、認証済みのユーザーがROLE_ADMINという権限を持っているかをチェックします。USERクラスで権限を設定する際は、oles("USER")のようにROLE_を省略しても、Spring Securityが内部で自動的に付与してくれます。

終わりに

Spring Securityはアプリケーションが立ち上がったときにDI注入される仕組みを利用し、アプリ実装者は3つのことだけを意識すれば強固なセキュリティ機能を使用できる、便利フレームワークです。

補足:
pring Securityは、設定クラスやUserDetailsServiceなどのコンポーネントを@Bean@ServiceとしてDIコンテナに登録し、それらを連携させて動作します。これはSpringフレームワークの基本です。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?