最新の安定バージョンについては、Spring Security 6.3.1 を使用してください!

フォームログイン

Spring Security は、html フォームで提供されるユーザー名とパスワードのサポートを提供します。このセクションでは、Spring Security 内でのフォームベース認証の動作について詳しく説明します。

フォームベースのログインが Spring Security 内でどのように機能するかを見てみましょう。まず、ユーザーがログインフォームにリダイレクトされる方法を確認します。

loginurlauthenticationentrypoint
図 1: ログインページへのリダイレクト

この図は、SecurityFilterChain ダイアグラムから構築されています。

number 1 最初に、ユーザーが認可されていないリソース /private に対して認証されていないリクエストを行います。

number 2Spring Security の FilterSecurityInterceptor は、認証されていないリクエストが AccessDeniedException をスローすることによって拒否されたことを示します。

number 3 ユーザーが認証されていないため、ExceptionTranslationFilter は認証の開始を開始し、構成された AuthenticationEntryPoint を使用してログインページにリダイレクトを送信します。ほとんどの場合、AuthenticationEntryPoint は LoginUrlAuthenticationEntryPoint (Javadoc) のインスタンスです。

number 4 ブラウザーは、リダイレクト先のログインページをリクエストします。

number 5 アプリケーション内の何かで、ログインページをレンダリングする必要があります。

ユーザー名とパスワードが送信されると、UsernamePasswordAuthenticationFilter はユーザー名とパスワードを認証します。UsernamePasswordAuthenticationFilter は AbstractAuthenticationProcessingFilter を継承しているため、この図はかなり似ているはずです。

usernamepasswordauthenticationfilter
図 2: ユーザー名とパスワードの認証

この図は、SecurityFilterChain ダイアグラムから構築されています。

number 1 ユーザーがユーザー名とパスワードを送信すると、UsernamePasswordAuthenticationFilter は HttpServletRequest からユーザー名とパスワードを抽出して Authentication の一種である UsernamePasswordAuthenticationToken を作成します。

number 2 次に、UsernamePasswordAuthenticationToken が AuthenticationManager に渡され、認証されます。AuthenticationManager がどのように見えるかの詳細は、ユーザー情報がどのように保存されているかによって異なります。

number 3 認証に失敗した場合、Failure

  • SecurityContextHolder はクリアされます。

  • RememberMeServices.loginFail が呼び出されます。設定されていないことを覚えていれば、これはノーオペレーションです。

  • AuthenticationFailureHandler が呼び出されます。

number 4 認証が成功した場合は、Success .

  • SessionAuthenticationStrategy に新しいログインが通知されます。

  • 認証SecurityContextHolder に設定されます。

  • RememberMeServices.loginSuccess が呼び出されます。設定されていないことを覚えていれば、これはノーオペレーションです。

  • ApplicationEventPublisher は InteractiveAuthenticationSuccessEvent を公開します。

  • AuthenticationSuccessHandler が呼び出されます。通常、これはログインページにリダイレクトするときに ExceptionTranslationFilter によって保存されたリクエストにリダイレクトする SimpleUrlAuthenticationSuccessHandler です。

Spring Security フォームログインはデフォルトで有効になっています。ただし、サーブレットベースの構成が提供されるとすぐに、フォームベースのログインを明示的に提供する必要があります。最小限の明示的な Java 構成を以下に示します。

フォームログイン
  • Java

  • XML

  • Kotlin

public SecurityFilterChain filterChain(HttpSecurity http) {
	http
		.formLogin(withDefaults());
	// ...
}
<http>
	<!-- ... -->
	<form-login />
</http>
open fun filterChain(http: HttpSecurity): SecurityFilterChain {
	http {
		formLogin { }
	}
	// ...
}

この構成では、Spring Security はデフォルトのログインページをレンダリングします。ほとんどの本番アプリケーションでは、カスタムログインフォームが必要です。

以下の構成は、カスタムログインフォームを提供する方法を示しています。

カスタムログインフォーム設定
  • Java

  • XML

  • Kotlin

public SecurityFilterChain filterChain(HttpSecurity http) {
	http
		.formLogin(form -> form
			.loginPage("/login")
			.permitAll()
		);
	// ...
}
<http>
	<!-- ... -->
	<intercept-url pattern="/login" access="permitAll" />
	<form-login login-page="/login" />
</http>
open fun filterChain(http: HttpSecurity): SecurityFilterChain {
	http {
		formLogin {
			loginPage = "/login"
			permitAll()
		}
	}
	// ...
}

ログインページが Spring Security 構成で指定されている場合、ページをレンダリングするのはユーザーの責任です。以下は、/login のログインページに準拠する HTML ログインフォームを生成する Thymeleaf (英語) テンプレートです。

ログインフォーム - src/main/resources/templates/login.html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="https://www.thymeleaf.org">
	<head>
		<title>Please Log In</title>
	</head>
	<body>
		<h1>Please Log In</h1>
		<div th:if="${param.error}">
			Invalid username and password.</div>
		<div th:if="${param.logout}">
			You have been logged out.</div>
		<form th:action="@{/login}" method="post">
			<div>
			<input type="text" name="username" placeholder="Username"/>
			</div>
			<div>
			<input type="password" name="password" placeholder="Password"/>
			</div>
			<input type="submit" value="Log in" />
		</form>
	</body>
</html>

デフォルトの HTML フォームにはいくつかの重要なポイントがあります。

  • フォームは post から /login を実行する必要があります

  • フォームには、Thymeleaf によって自動的に含まれる CSRF トークンを含める必要があります。

  • フォームは、username という名前のパラメーターでユーザー名を指定する必要があります

  • フォームは、password という名前のパラメーターでパスワードを指定する必要があります

  • HTTP パラメーターエラーが見つかった場合、ユーザーが有効なユーザー名 / パスワードの入力に失敗したことを示します

  • HTTP パラメーターログアウトが見つかった場合、ユーザーが正常にログアウトしたことを示します

多くのユーザーは、ログインページをカスタマイズする以上のことは必要ありません。ただし、必要に応じて、上記のすべてを追加の構成でカスタマイズできます。

Spring MVC を使用している場合は、GET /login を作成したログインテンプレートにマップするコントローラーが必要になります。最小限のサンプル LoginController を以下に示します。

LoginController
  • Java

  • Kotlin

@Controller
class LoginController {
	@GetMapping("/login")
	String login() {
		return "login";
	}
}
@Controller
class LoginController {
    @GetMapping("/login")
    fun login(): String {
        return "login"
    }
}