カテゴリ: Spring 更新日: 2025/12/15

Spring Securityで認証失敗や権限不足の例外をハンドリングする方法を徹底解説

例外ハンドリング:認証失敗/権限不足をハンドラーで制御する
例外ハンドリング:認証失敗/権限不足をハンドラーで制御する

先生と生徒の会話形式で理解しよう

生徒

「Spring Securityでログインに失敗したときって、どうやってエラーメッセージを表示したり、リダイレクトを制御するんですか?」

先生

「それはAuthenticationFailureHandlerを使って処理をカスタマイズすることでできますよ。また、ログイン済みでもアクセス権限がない場合にはAccessDeniedHandlerを使います。」

生徒

「じゃあ、自分でそのハンドラーを作成して登録すれば、好きなように制御できるんですね!」

先生

「その通りです。これから実際の使い方を順番に見ていきましょう!」

1. Spring Securityの例外ハンドリングとは?

1. Spring Securityの例外ハンドリングとは?
1. Spring Securityの例外ハンドリングとは?

Spring Securityはデフォルトでログイン失敗時やアクセス拒否時に自動的なエラーページへ遷移させますが、これを自分で制御したい場合は、専用のハンドラークラスを作成して設定します。

具体的には以下の2つを使います。

  • AuthenticationFailureHandler:認証失敗時(ログイン失敗)を制御
  • AccessDeniedHandler:権限不足時(403エラー)を制御

それぞれを独自に実装して、Spring Securityの設定に組み込むことで、認証処理の流れを柔軟にカスタマイズできます。

2. 認証失敗時を制御するAuthenticationFailureHandlerの実装方法

2. 認証失敗時を制御するAuthenticationFailureHandlerの実装方法
2. 認証失敗時を制御するAuthenticationFailureHandlerの実装方法

ログインフォームでパスワードを間違えたなど、認証に失敗したときの処理をカスタマイズするにはAuthenticationFailureHandlerを実装します。

以下にその例を示します。


@Component
public class CustomAuthFailureHandler implements AuthenticationFailureHandler {
    @Override
    public void onAuthenticationFailure(HttpServletRequest request,
                                        HttpServletResponse response,
                                        AuthenticationException exception)
                                        throws IOException, ServletException {
        response.sendRedirect("/login?error=true");
    }
}

このように、ログイン失敗時に指定のURL(ここでは/login?error=true)へリダイレクトするように設定できます。

3. 権限不足時のエラー制御:AccessDeniedHandlerの使い方

3. 権限不足時のエラー制御:AccessDeniedHandlerの使い方
3. 権限不足時のエラー制御:AccessDeniedHandlerの使い方

ログインは成功しているが、アクセス先に対する権限が足りない場合はAccessDeniedHandlerを使います。


@Component
public class CustomAccessDeniedHandler implements AccessDeniedHandler {
    @Override
    public void handle(HttpServletRequest request,
                       HttpServletResponse response,
                       AccessDeniedException accessDeniedException)
                       throws IOException, ServletException {
        response.sendRedirect("/access-denied");
    }
}

このようにして、403エラー画面の代わりに独自のエラーページへ誘導することができます。

4. Spring Securityへのハンドラー登録方法

4. Spring Securityへのハンドラー登録方法
4. Spring Securityへのハンドラー登録方法

上記で作成したAuthenticationFailureHandlerAccessDeniedHandlerを、Spring Securityの設定クラス内で登録します。


@Configuration
@EnableWebSecurity
public class SecurityConfig {
    
    @Autowired
    private CustomAuthFailureHandler customAuthFailureHandler;

    @Autowired
    private CustomAccessDeniedHandler customAccessDeniedHandler;

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .formLogin(form -> form
                .loginPage("/login")
                .failureHandler(customAuthFailureHandler)
            )
            .exceptionHandling(ex -> ex
                .accessDeniedHandler(customAccessDeniedHandler)
            );

        return http.build();
    }
}

これで、ログイン失敗時にはCustomAuthFailureHandlerが、権限不足時にはCustomAccessDeniedHandlerが呼ばれるようになります。

5. 認証エラー情報をログイン画面に表示する

5. 認証エラー情報をログイン画面に表示する
5. 認証エラー情報をログイン画面に表示する

エラー時に/login?error=trueのようにクエリパラメータを付けてリダイレクトすることで、ログイン画面にエラーメッセージを表示できます。


<form method="post" action="/login">
    <input type="text" name="username" />
    <input type="password" name="password" />
    <button type="submit">ログイン</button>
    <div th:if="${param.error}">
        <span class="text-danger">ユーザー名またはパスワードが違います。</span>
    </div>
</form>

このようにして、ユーザーにわかりやすくエラーを通知できます。

6. よくある失敗例とその対処法

6. よくある失敗例とその対処法
6. よくある失敗例とその対処法

ハンドラーが呼ばれないというトラブルもあります。次のような原因が考えられます。

  • SecurityFilterChainにハンドラーの登録を忘れている
  • カスタムハンドラーに@Componentがついていない
  • URLマッピングが誤っていて正しいパスに遷移できない

これらはエラーログやデバッグで確認しながら1つずつ潰していくのがポイントです。

7. 認証成功時も制御したい場合は?

7. 認証成功時も制御したい場合は?
7. 認証成功時も制御したい場合は?

AuthenticationSuccessHandlerを使うことで、ログイン成功後の処理も自由に制御できます。


@Component
public class CustomAuthSuccessHandler implements AuthenticationSuccessHandler {
    @Override
    public void onAuthenticationSuccess(HttpServletRequest request,
                                        HttpServletResponse response,
                                        Authentication authentication)
                                        throws IOException, ServletException {
        response.sendRedirect("/dashboard");
    }
}

これでログイン成功後に/dashboardへ遷移するようになります。

8. 403ページをデザインする方法

8. 403ページをデザインする方法
8. 403ページをデザインする方法

/access-deniedにリダイレクトされたときに表示するページを自分で作るには、HTMLを用意してそこに説明やデザインを加えます。


<!DOCTYPE html>
<html>
<head>
    <title>アクセス拒否</title>
</head>
<body>
    <h1>アクセスが拒否されました</h1>
    <p>このページにアクセスする権限がありません。</p>
    <a href="/">トップページへ戻る</a>
</body>
</html>

まとめ

まとめ
まとめ

Spring Securityにおける例外ハンドリングの全体像

本記事では、Spring Securityを利用したWebアプリケーション開発において重要となる、 認証失敗や権限不足といった例外をどのようにハンドリングするかについて詳しく解説してきました。 Spring Securityはデフォルトでも一定の動作を提供してくれますが、 実務レベルではユーザー体験やセキュリティ要件に合わせて、 ログイン失敗時やアクセス拒否時の挙動を細かく制御する必要があります。 その際に中心となるのが、AuthenticationFailureHandlerやAccessDeniedHandlerといった 専用のハンドラーインターフェースです。

AuthenticationFailureHandlerは、ユーザー名やパスワードの誤りなど、 認証そのものが失敗した場合に呼び出されます。 これを使うことで、ログイン画面へのリダイレクト先を変更したり、 クエリパラメータを付与してエラーメッセージを表示したりといった柔軟な制御が可能になります。 一方で、AccessDeniedHandlerはログイン済みであるにもかかわらず、 権限不足によってアクセスが拒否された場合に利用されます。 両者の役割を正しく理解することが、Spring Securityの例外ハンドリングを使いこなす第一歩です。

設定クラスとハンドラー登録の重要性

カスタムハンドラーを作成しただけでは、Spring Securityの動作は変わりません。 SecurityFilterChainの設定クラス内で、formLoginやexceptionHandlingに対して 明示的にハンドラーを登録する必要があります。 この設定を忘れてしまうと、「クラスは作ったのに処理が呼ばれない」 という状況に陥りがちです。 また、@Componentアノテーションの付け忘れや、 URLパスの指定ミスもよくある原因として挙げられます。 例外ハンドリングが正しく動作しない場合は、 設定クラスとハンドラーの紐付けを最初に確認する癖をつけましょう。

まとめとしてのサンプル構成イメージ

最後に、認証失敗と権限不足の両方を意識した、 Spring Security設定のシンプルなイメージを整理しておきます。 実際の開発では、この構成をベースに画面遷移やメッセージ表示を調整していくと、 見通しの良いセキュリティ設計が可能になります。


@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Autowired
    private CustomAuthFailureHandler customAuthFailureHandler;

    @Autowired
    private CustomAccessDeniedHandler customAccessDeniedHandler;

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .formLogin(form -> form
                .loginPage("/login")
                .failureHandler(customAuthFailureHandler)
            )
            .exceptionHandling(ex -> ex
                .accessDeniedHandler(customAccessDeniedHandler)
            );
        return http.build();
    }
}

このように、認証失敗と権限不足を明確に分けてハンドリングすることで、 ユーザーにとって分かりやすく、管理者にとっても保守しやすい構成になります。 Spring Securityは最初こそ設定項目が多く感じられますが、 仕組みを理解してしまえば、セキュアで柔軟な認証基盤を構築できる強力なフレームワークです。

先生と生徒の振り返り会話

生徒

「認証失敗と権限不足で、使うハンドラーが違う理由がよく分かりました。 なんとなくエラー処理をしていた頃より、頭の中が整理できた気がします。」

先生

「それは良いですね。Spring Securityでは、 どの段階でエラーが起きているのかを意識することがとても大切です。 認証なのか、認可なのかを切り分けられるようになると、 設定の理解も一気に深まります。」

生徒

「ハンドラーを登録し忘れると動かない、という点も印象に残りました。 設定クラスの確認を最初にするようにします。」

先生

「その意識はとても大事ですよ。 セキュリティ設定は小さなミスが大きな挙動の違いにつながります。 一つ一つの設定の意味を理解しながら進めていきましょう。」

生徒

「これでログインエラーや権限エラーを、 自信を持ってカスタマイズできそうです。」

先生

「その調子です。 今回学んだ内容は、実務でも頻繁に使う重要なポイントなので、 ぜひ自分のプロジェクトで試してみてください。」

Springの学習を効率化したい方へ

この記事の内容をもっと深く知るには、以下の入門書が最適です。

Spring Framework超入門をAmazonで見る
カテゴリの一覧へ
新着記事
New1
Java
Javaのラムダ式で注意したい変数キャプチャの落とし穴とは?代入と変数名のベストプラクティス解説
更新記事
New2
Spring
Springの@GetMappingアノテーションの使い方を徹底解説!初心者でもわかるSpring Boot入門
更新記事
New3
Spring
SpringDataJPAのJPAクエリメソッド「EndingWith」の使い方を完全ガイド!初心者向け解説
更新記事
New4
Spring
SpringDataJPAのJPAクエリメソッド「StartingWith」の使い方を完全ガイド!初心者向け解説
更新記事
人気記事
No.1
Java&Spring記事人気No1
Spring
Spring BootとJavaの互換性一覧!3.5/3.4/3.3はJava 21・17に対応してる?
No.2
Java&Spring記事人気No2
Java
JavaのBooleanクラスの使い方を完全ガイド!初心者でもわかる真偽値の操作
No.3
Java&Spring記事人気No3
JSP
JSPの基本タグ一覧と使い方まとめ!実務で使えるタグを紹介
No.4
Java&Spring記事人気No4
Java
JavaのIOExceptionクラス徹底解説!初心者向けファイル入出力エラー対策ガイド
No.5
Java&Spring記事人気No5
Spring
SpringのBindingResultを完全ガイド!初心者でもわかる入力チェックとエラー処理
No.6
Java&Spring記事人気No6
JSP
JSPでif文・for文を使う方法!初心者でもわかるJavaとの違いと使い方
No.7
Java&Spring記事人気No7
Spring
SpringのModelクラスとaddAttributeメソッドの使い方を完全ガイド!初心者でも安心
No.8
Java&Spring記事人気No8
Spring
SpringDataJPAのJPAクエリメソッド「EndingWith」の使い方を完全ガイド!初心者向け解説