このガイドでは、Spring Security で保護されているリソースを使用して単純な Web アプリケーションを作成するプロセスを順を追って説明します。
構築するもの
ユーザーの固定リストによるログインフォームでページを保護する Spring MVC アプリケーションを構築します。
必要なもの
約 15 分
お気に入りのテキストエディターまたは IDE
コードを直接 IDE にインポートすることもできます。
このガイドを完了する方法
ほとんどの Spring 入門ガイドと同様に、最初から始めて各ステップを完了するか、すでに慣れている場合は基本的なセットアップステップをバイパスできます。いずれにしても、最終的に動作するコードになります。
最初から始めるには、Spring Initializr から開始に進みます。
基本をスキップするには、次の手順を実行します。
このガイドのソースリポジトリをダウンロードして解凍するか、Git (英語) を使用してクローンを作成します。
git clone https://github.com/spring-guides/gs-securing-web.git (英語)
gs-securing-web/initial
に cd保護されていない Web アプリケーションを作成するにジャンプしてください。
完了したときは、gs-securing-web/complete
のコードに対して結果を確認できます。
Spring Initializr から開始
すべての Spring アプリケーションでは、Spring Initializr (英語) から始める必要があります。Initializr は、アプリケーションに必要なすべての依存関係をすばやく取り込む方法を提供し、多くの設定を行います。この例では、Spring、Web および Thymeleaf の依存関係が必要です。
次のリストは、Maven を選択したときに作成される 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>2.3.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>securing-web</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>securing-web</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</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-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
次のリストは、Gradle を選択したときに作成される build.gradle
ファイルを示しています。
plugins {
id 'org.springframework.boot' version '2.3.2.RELEASE'
id 'io.spring.dependency-management' version '1.0.8.RELEASE'
id 'java'
}
group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-web'
testImplementation('org.springframework.boot:spring-boot-starter-test') {
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
}
}
test {
useJUnitPlatform()
}
保護されていない Web アプリケーションを作成する
Web アプリケーションにセキュリティを適用する前に、保護する Web アプリケーションが必要です。このセクションでは、簡単な Web アプリケーションを作成する方法を説明します。次に、次のセクションで Spring Security で保護します。
Web アプリケーションには、ホームページと「Hello, World」ページの 2 つの単純なビューが含まれています。ホームページは、次の Thymeleaf テンプレート(src/main/resources/templates/home.html
から)で定義されています。
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="https://www.thymeleaf.org" xmlns:sec="https://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
<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>
この単純なビューには、/hello
ページへのリンクが含まれています。このページは、次の Thymeleaf テンプレートで定義されています(src/main/resources/templates/hello.html
から)。
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="https://www.thymeleaf.org"
xmlns:sec="https://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
<head>
<title>Hello World!</title>
</head>
<body>
<h1>Hello world!</h1>
</body>
</html>
Web アプリケーションは Spring MVC に基づいています。そのため、Spring MVC を構成し、View Controller をセットアップしてこれらのテンプレートを公開する必要があります。次のリスト(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
クロージャーに 2 行(アプリケーション用とテスト用)を追加する必要があります。
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.security:spring-security-test'
次のリストは、完成した build.gradle
ファイルを示しています。
plugins {
id 'org.springframework.boot' version '2.3.2.RELEASE'
id 'io.spring.dependency-management' version '1.0.8.RELEASE'
id 'java'
}
group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.security:spring-security-test'
testImplementation('org.springframework.boot:spring-boot-starter-test') {
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
}
}
test {
useJUnitPlatform()
}
Maven では、次のリストに示すように、pom.xml
の <dependencies>
要素に 2 つの追加エントリ(アプリケーション用とテスト用)を追加する必要があります。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</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>2.3.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>securing-web</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>securing-web</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</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.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>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</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.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
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;
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/", "/home").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
}
@Bean
@Override
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 統合を提供します。また、WebSecurityConfigurerAdapter
を継承し、いくつかのメソッドをオーバーライドして、Web セキュリティ構成のいくつかの詳細を設定します。
configure(HttpSecurity)
メソッドは、セキュリティで保護する必要がある URL パスと保護しない URL パスを定義します。具体的には、/
および /home
パスは、認証を必要としないように構成されています。他のすべてのパスは認証される必要があります。
ユーザーが正常にログインすると、認証を必要とする以前にリクエストされたページにリダイレクトされます。カスタム /login
ページ(loginPage()
で指定されている)があり、誰でもそれを表示できます。
userDetailsService()
メソッドは、単一のユーザーでメモリ内ユーザーストアをセットアップします。そのユーザーには、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"
xmlns:sec="https://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
<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-springsecurity3">
<head>
<title>Hello World!</title>
</head>
<body>
<h1 th:inline="text">Hello [[${#httpServletRequest.remoteUser}]]!</h1>
<form th:action="@{/logout}" method="post">
<input type="submit" value="Sign Out"/>
</form>
</body>
</html>
Spring Security と HttpServletRequest#getRemoteUser()
の統合を使用して、ユーザー名を表示します。「サインアウト」フォームは、POST を /logout
に送信します。ログアウトに成功すると、ユーザーを /login?logout
にリダイレクトします。
アプリケーションの実行
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 クリエイティブコモンズライセンス (英語) でリリースされています。 |