カテゴリ: 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へのハンドラー登録方法

上記で作成したAuthenticationFailureHandlerとAccessDeniedHandlerを、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では、 どの段階でエラーが起きているのかを意識することがとても大切です。 認証なのか、認可なのかを切り分けられるようになると、 設定の理解も一気に深まります。」

生徒

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

先生

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

生徒

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

先生

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

生成AIを基礎から学びたい方へ

ChatGPTなどの生成AIをこれから学びたい方に向けて、AIスキルアカデミーの口コミ・評判、料金、無料セミナーの内容を詳しくまとめています。

AIスキルアカデミーの口コミ・評判を詳しく見る
カテゴリの一覧へ
新着記事
New1
Java
JavaのassertFalseとは?JUnit5のAssertionsクラスを初心者向けにわかりやすく解説
新規投稿
New2
Thymeleaf
ThymeleafでDBから取得したデータを編集フォームの初期値にセットする方法!Entity連携を初心者向けに解説
新規投稿
New3
Spring
JavaのSpringで使う@FutureOrPresentアノテーションを完全ガイド!初心者でもわかる日付バリデーション
新規投稿
New4
Java
JavaのLocalDateクラスのgetMonthValueメソッド完全ガイド!初心者でもわかる数値で月を取得する方法
新規投稿
人気記事
No.1
Java&Spring記事人気No1
Servlet
JavaサーブレットのdoPostメソッドとは?初心者向けにやさしく解説!
No.2
Java&Spring記事人気No2
Servlet
JavaのHttpServletResponseクラスを初心者向けに徹底解説!
No.3
Java&Spring記事人気No3
Servlet
JavaのHttpServletRequestWrapperとgetSessionメソッドの使い方を徹底解説!初心者向けServletのセッション管理入門
No.4
Java&Spring記事人気No4
Servlet
JavaのServletExceptionクラスを初心者向けに徹底解説!
No.5
Java&Spring記事人気No5
Servlet
JavaのHttpSessionインターフェースとgetSessionContextメソッドを徹底解説!初心者でもわかるセッション管理の基本
No.6
Java&Spring記事人気No6
Java
JavaのStringクラスとlengthメソッドを完全解説!初心者でも理解できる文字列の長さ取得の使い方
No.7
Java&Spring記事人気No7
Servlet
JavaのHttpSessionAttributeListenerとattributeRemovedメソッドの使い方を徹底解説!初心者でもわかるセッション属性の削除と監視
No.8
Java&Spring記事人気No8
Java
Javaのクラスとインスタンス化、コンストラクタの使い方完全ガイド!初心者でもわかるオブジェクト指向の基礎