<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="https://www.thymeleaf.org">
<head>
<title>Spring Security Example</title>
</head>
<body>
<h1>Welcome!</h1>
<p>Click <a th:href="@{/hello}">here</a> to see a greeting.</p>
</body>
</html>
Spring Boot ログイン画面
このガイドでは、Spring Security で保護されているリソースを使用して単純な Web アプリケーションを作成するプロセスを順を追って説明します。
構築するもの
固定のユーザーリストに基づくログインフォームを使用してページを保護する Spring MVC アプリケーションを構築します。
必要なもの
約 15 分
Eclipse STS や IntelliJ IDEA のような任意の IDE または VSCode のようなテキストエディター
Java 17 以降
コードを直接 IDE にインポートすることもできます。
本ガイドの完成までの流れ
ほとんどの Spring 入門ガイドと同様に、最初から始めて各ステップを完了するか、すでに慣れている場合は基本的なセットアップステップをバイパスできます。いずれにしても、最終的に動作するコードになります。
最初から始めるには、Spring Initializr から開始に進みます。
基本をスキップするには、次の手順を実行します。
このガイドを Eclipse で「Spring 入門コンテンツのインポート」するか、ソースリポジトリをダウンロードして解凍、または、Git (英語) を使用してクローンを作成します。
git clone https://github.com/spring-guides/gs-securing-web.git
gs-securing-web/initial
に cd保護されていない Web アプリケーションを作成するにジャンプしてください。
完了したときは、gs-securing-web/complete
のコードに対して結果を確認できます。
Spring Initializr から開始
IDE を使用する場合はプロジェクト作成ウィザードを使用します。IDE を使用せずにコマンドラインなどで開発する場合は、この事前に初期化されたプロジェクトからプロジェクトを ZIP ファイルとしてダウンロードできます。このプロジェクトは、このチュートリアルの例に合うように構成されています。
プロジェクトを手動で初期化するには:
IDE のメニューまたはブラウザーから Spring Initializr を開きます。アプリケーションに必要なすべての依存関係を取り込み、ほとんどのセットアップを行います。
Gradle または Maven のいずれかと、使用する言語を選択します。このガイドは、Java を選択したことを前提としています。
依存関係をクリックし、Spring Web と Thymeleaf を選択します。
生成をクリックします。
結果の ZIP ファイルをダウンロードします。これは、選択して構成された Web アプリケーションのアーカイブです。
Eclipse や IntelliJ のような IDE は新規プロジェクト作成ウィザードから Spring Initializr の機能が使用できるため、手動での ZIP ファイルのダウンロードやインポートは不要です。 |
プロジェクトを Github からフォークして、IDE または他のエディターで開くこともできます。 |
保護されていない Web アプリケーションを作成する
Web アプリケーションにセキュリティを適用する前に、保護する Web アプリケーションが必要です。このセクションでは、簡単な Web アプリケーションを作成する方法を説明します。次に、次のセクションで Spring Security で保護します。
Web アプリケーションには、ホームページと "Hello, World" ページの 2 つの単純なビューが含まれています。ホームページは、次の Thymeleaf テンプレート(src/main/resources/templates/home.html
から)で定義されています。
この単純なビューには、/hello
ページへのリンクが含まれています。このページは、次の Thymeleaf テンプレートで定義されています(src/main/resources/templates/hello.html
から)。
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="https://www.thymeleaf.org">
<head>
<title>Hello World!</title>
</head>
<body>
<h1>Hello world!</h1>
</body>
</html>
Web アプリケーションは Spring MVC に基づいています。その結果、Spring MVC を構成し、これらのテンプレートを公開するようにビューコントローラーを設定する必要があります。次のリスト ( src/main/java/com/example/securingweb/MvcConfig.java
から) は、アプリケーションで Spring MVC を構成するクラスを示しています。
package com.example.securingweb;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class MvcConfig implements WebMvcConfigurer {
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/home").setViewName("home");
registry.addViewController("/").setViewName("home");
registry.addViewController("/hello").setViewName("hello");
registry.addViewController("/login").setViewName("login");
}
}
addViewControllers()
メソッド(WebMvcConfigurer
の同じ名前のメソッドをオーバーライドする)は、4 つの View Controller を追加します。2 つの View Controller は、名前が home
(home.html
で定義)のビューを参照し、別の View Controller は hello
(hello.html
で定義)という名前のビューを参照します。4 番目の View Controller は、login
という名前の別のビューを参照します。次のセクションでそのビューを作成します。
この時点で、"アプリケーションの実行" にジャンプして、何にもログインすることなくアプリケーションを実行できます。
セキュリティで保護されていない Web アプリケーションができたため、セキュリティを追加できます。
Spring Security をセットアップする
権限のないユーザーが /hello
のグリーティングページを表示できないようにしたいとします。現在のように、訪問者がホームページのリンクをクリックすると、彼らを止める障壁のない挨拶が表示されます。訪問者がそのページを見る前にサインインすることを強制するバリアを追加する必要があります。
そのためには、アプリケーションで Spring Security を構成します。Spring Security がクラスパスにある場合、Spring Boot は「基本」認証ですべての HTTP エンドポイントを自動的に保護します。ただし、セキュリティ設定をさらにカスタマイズできます。最初に行う必要があるのは、Spring Security をクラスパスに追加することです。
Gradle では、次のように、build.gradle
の dependencies
クロージャーに 3 行 (アプリケーション用、Thymeleaf と Spring Security 統合用、およびテスト用) を追加する必要があります。
implementation 'org.springframework.boot:spring-boot-starter-security'
// Temporary explicit version to fix Thymeleaf bug
implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity6:3.1.2.RELEASE'
testImplementation 'org.springframework.security:spring-security-test'
次のリストは、完成した build.gradle
ファイルを示しています。
plugins {
id 'java'
id 'org.springframework.boot' version '3.3.0'
}
apply plugin: 'io.spring.dependency-management'
group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '17'
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-security'
// Temporary explicit version to fix Thymeleaf bug
implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity6:3.1.2.RELEASE'
testImplementation 'org.springframework.security:spring-security-test'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
test {
useJUnitPlatform()
}
Maven では、次のように、pom.xml
の <dependencies>
要素に 2 つの追加エントリ(アプリケーション用とテスト用)を追加する必要があります。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity6</artifactId>
<!-- Temporary explicit version to fix Thymeleaf bug -->
<version>3.1.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
次のリストは、完成した pom.xml
ファイルを示しています。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>securing-web-complete</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>securing-web-complete</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity6</artifactId>
<!-- Temporary explicit version to fix Thymeleaf bug -->
<version>3.1.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
次のセキュリティ構成(src/main/java/com/example/securingweb/WebSecurityConfig.java
から)により、認証されたユーザーのみがシークレットグリーティングを見ることができます。
package com.example.securingweb;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
@EnableWebSecurity
public class WebSecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests((requests) -> requests
.requestMatchers("/", "/home").permitAll()
.anyRequest().authenticated()
)
.formLogin((form) -> form
.loginPage("/login")
.permitAll()
)
.logout((logout) -> logout.permitAll());
return http.build();
}
@Bean
public UserDetailsService userDetailsService() {
UserDetails user =
User.withDefaultPasswordEncoder()
.username("user")
.password("password")
.roles("USER")
.build();
return new InMemoryUserDetailsManager(user);
}
}
WebSecurityConfig
クラスには @EnableWebSecurity
のアノテーションが付けられ、Spring Security の Web セキュリティサポートを有効にし、Spring MVC 統合を提供します。また、2 つの Bean を公開して、Web セキュリティ構成の詳細を設定します。
SecurityFilterChain
Bean は、保護する URL パスと保護しない URL パスを定義します。具体的には、/
パスと /home
パスは、認証を必要としないように構成されています。他のすべてのパスは認証する必要があります。
ユーザーが正常にログインすると、認証を必要とする以前にリクエストされたページにリダイレクトされます。カスタム /login
ページ(loginPage()
で指定されている)があり、誰でもそれを表示できます。
UserDetailsService
Bean は、1 人のユーザーでメモリ内ユーザーストアをセットアップします。そのユーザーには、user
のユーザー名、password
のパスワード、および USER
のロールが与えられます。
次に、ログインページを作成する必要があります。login
ビュー用の View Controller がすでに存在するため、次のリスト(src/main/resources/templates/login.html
から)が示すように、ログインビュー自体を作成するだけで済みます。
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="https://www.thymeleaf.org">
<head>
<title>Spring Security Example </title>
</head>
<body>
<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><label> User Name : <input type="text" name="username"/> </label></div>
<div><label> Password: <input type="password" name="password"/> </label></div>
<div><input type="submit" value="Sign In"/></div>
</form>
</body>
</html>
この Thymeleaf テンプレートは、ユーザー名とパスワードを取得して /login
に投稿するフォームを提示します。構成されているように、Spring Security はそのリクエストをインターセプトし、ユーザーを認証するフィルターを提供します。ユーザーが認証に失敗すると、ページは /login?error
にリダイレクトされ、ページに適切なエラーメッセージが表示されます。ログアウトに成功すると、アプリケーションが /login?logout
に送信され、ページに適切な成功メッセージが表示されます。
最後に、現在のユーザー名を表示してサインアウトする方法を訪問者に提供する必要があります。これを行うには、次のリスト(src/main/resources/templates/hello.html
から)が示すように、hello.html
を更新して現在のユーザーに挨拶し、Sign Out
フォームを含めます。
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="https://www.thymeleaf.org"
xmlns:sec="https://www.thymeleaf.org/thymeleaf-extras-springsecurity6">
<head>
<title>Hello World!</title>
</head>
<body>
<h1 th:inline="text">Hello <span th:remove="tag" sec:authentication="name">thymeleaf</span>!</h1>
<form th:action="@{/logout}" method="post">
<input type="submit" value="Sign Out"/>
</form>
</body>
</html>
Thymeleaf の Spring Security との統合を使用して、ユーザー名を表示します。「サインアウト」フォームは POST を /logout
に送信します。ログアウトに成功すると、ユーザーを /login?logout
にリダイレクトします。
Thymeleaf 3.1 は HttpServletRequest へのアクセスを提供しなくなったため、HttpServletRequest#getRemoteUser() を使用して現在認証されているユーザーにアクセスすることはできません。 |
アプリケーションの実行
Spring Initializr は、アプリケーションクラスを作成します。この場合、クラスを変更する必要はありません。次のリスト(src/main/java/com/example/securingweb/SecuringWebApplication.java
から)は、アプリケーションクラスを示しています。
package com.example.securingweb;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SecuringWebApplication {
public static void main(String[] args) throws Throwable {
SpringApplication.run(SecuringWebApplication.class, args);
}
}
実行可能 JAR を構築する
コマンドラインから Gradle または Maven を使用してアプリケーションを実行できます。必要なすべての依存関係、クラス、リソースを含む単一の実行可能 JAR ファイルを構築して実行することもできます。実行可能な jar を構築すると、開発ライフサイクル全体、さまざまな環境などで、アプリケーションとしてサービスを簡単に提供、バージョン管理、デプロイできます。
Gradle を使用する場合、./gradlew bootRun
を使用してアプリケーションを実行できます。または、次のように、./gradlew build
を使用して JAR ファイルをビルドしてから、JAR ファイルを実行できます。
Maven を使用する場合、./mvnw spring-boot:run
を使用してアプリケーションを実行できます。または、次のように、./mvnw clean package
で JAR ファイルをビルドしてから、JAR ファイルを実行できます。
ここで説明する手順は、実行可能な JAR を作成します。クラシック WAR ファイルを作成することもできます。 |
アプリケーションが起動したら、ブラウザーで http://localhost:8080
を指定します。次のイメージが示すように、ホームページが表示されます。
リンクをクリックすると、/hello
のグリーティングページに移動しようとします。ただし、そのページは保護されており、まだログインしていないため、次のイメージに示すように、ログインページに移動します。
セキュリティで保護されていないバージョンでここにジャンプした場合、ログインページは表示されません。セキュリティベースのコードの残りをバックアップして作成する必要があります。 |
ログインページで、ユーザー名とパスワードのフィールドにそれぞれ user
と password
を入力して、テストユーザーとしてサインインします。ログインフォームを送信すると、認証され、次のイメージに示すようにグリーティングページに移動します。
サインアウトボタンをクリックすると、認証が取り消され、ログアウトされたことを示すメッセージとともにログインページに戻ります。
要約
おめでとう! Spring Security で保護された単純な Web アプリケーションを開発しました。
関連事項
次のガイドも役立ちます。
新しいガイドを作成したり、既存のガイドに貢献したいですか? 投稿ガイドラインを参照してください [GitHub] (英語) 。
すべてのガイドは、コード用の ASLv2 ライセンス、およびドキュメント用の Attribution、NoDerivatives creative commons ライセンス (英語) でリリースされています。 |