Spring フレームワークによる Web アプリケーション開発で、ログイン処理を実装する際は Spring Security が便利です。ここでは特に Spring Boot で Web アプリケーションを開発する場合を対象とし、フォームによる ID/Password ログインを行うためのサンプルコードをまとめます。
公式ドキュメント
- Spring Security チュートリアル
- Spring Boot ユーザーガイド / Security
- Spring Security ユーザーガイド
フォームログインのサンプル
基本的な Gradle プロジェクトです。ここでは簡単のため、フォームでログインするユーザーは、DB ではなく Java ソースコードにハードコーディングされたものを利用します。
.
|-- build.gradle
|-- gradle
| `-- wrapper
| |-- gradle-wrapper.jar
| `-- gradle-wrapper.properties
|-- gradlew
|-- gradlew.bat
`-- src
`-- main
|-- java
| `-- hello
| |-- Application.java
| |-- MvcConfig.java
| `-- WebSecurityConfig.java
`-- resources
`-- templates
|-- hello.html
|-- home.html
`-- login.html
build.gradle
buildscript {
ext {
springBootVersion = '1.5.3.RELEASE'
}
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'org.springframework.boot'
jar {
baseName = 'gs-spring-boot'
version = '0.1.0'
}
repositories {
mavenCentral()
}
sourceCompatibility = 1.8
targetCompatibility = 1.8
dependencies {
compile('org.springframework.boot:spring-boot-starter-thymeleaf')
compile('org.springframework.boot:spring-boot-starter-security')
compile('org.springframework.boot:spring-boot-devtools')
}
- Spring Boot から Spring Security を利用するためには
spring-boot-starter-security
を設定します。 spring-boot-starter-thymeleaf
は Thymeleaf の設定です。./gradlew dependencies
を実行するとspring-boot-starter-web
も依存先としてインストールされることが分かります。spring-boot-devtools
で開発時に便利な機能を利用できるようになります。
Java ソースコード
src/main/java/hello/Application.java
package hello;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
src/main/java/hello/MvcConfig.java
今回のサンプルコードでは @Controller
コントローラが登場せず、@RequestMapping("/")
設定がなされません。代わりに、以下の Config Java ファイルでパスと View のマッピングを行っています。
package hello;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
@Configuration
public class MvcConfig extends WebMvcConfigurerAdapter {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/home").setViewName("home");
registry.addViewController("/").setViewName("home");
registry.addViewController("/hello").setViewName("hello");
registry.addViewController("/login").setViewName("login");
}
}
src/main/java/hello/WebSecurityConfig.java
@EnableWebSecurity
アノテーションが設定されて WebSecurityConfigurerAdapter
を継承したクラスで Spring Security の既定の挙動をカスタマイズできます。ユーザー名が user でパスワードはアプリケーション起動時にログで確認できる Basic 認証が既定ですが、以下ではログインフォーム認証をユーザ名 user
パスワード password
で行うように変更しています。
パスに関する設定の意味はそれぞれ以下のとおりです。いずれも公式ドキュメントで更に詳細な設定が可能なことが確認できます。
- .authorizeRequests() パス
/
と/home
は認証なしで表示できるように設定しています。 - .formLogin() 認証用のパスを設定しています。
- .logout() ログアウト用のエンドポイントが自動生成されるように設定しています。
WebSecurityConfig.java
package hello;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
@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();
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER"); // sets up an in-memory user store with a single user.
}
}
HTML ファイル
Thymeleaf を利用しています。xmlns:th="http://www.thymeleaf.org"
は IDE の警告表示を回避するための設定です。
src/main/resources/templates/home.html
ログインせずに表示できるホームページです。
<!DOCTYPE html>
<html xmlns:th="http://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>
src/main/resources/templates/hello.html
ログインが必要なページです。ホームページからリンクされています。ログアウトするためのフォームも設置されています。#httpServletRequest.remoteUser
は HttpServletRequest#getRemoteUser()
を利用するための Thymeleaf の記法です。
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<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>
src/main/resources/templates/login.html
ユーザー名とパスワードを POST するためのログインフォームです。クエリストリングで /login?error
および /login?logout
がパラメータとして渡された際に表示するメッセージを Thymelaf の param
で判別して表示しています。
<!DOCTYPE html>
<html xmlns:th="http://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>
LDAP サーバーを利用したログイン認証
本ページでは簡単のため、Java ソースコードにハードコーディングされた auth.inMemoryAuthentication() を利用しました。実際にアプリケーションを開発する際はその他の認証方法を利用します。例えば LDAP を利用する場合は auth.ldapAuthentication() を設定します。
関連記事
- Java配列の宣言方法 (C/C++との違い)Javaの配列 Javaの配列宣言方法はC/C++と似ているようで若干異なる。 初期化しない場合 C/C++の int array[10]; はJavaでは int array[] = new int[10]; となる。同様にC/C++の int array[3][3]; はJavaでは int array[][] = new int[3][3]; となる。 初期化
- PlantUML による UML 図の描き方PlantUML はテキスト形式で表現されたシーケンス図やクラス図といった UML (Unified Modeling Language) 図の情報から画像を生成するためのツールです。簡単な使い方をまとめます。 インストール方法の選択 Atom や Eclipse のプラグインをインストールしてエディタから利用する方法、JAR をダウンロードして Java コマンドで実行する方法、Redmine ...
- Akka HTTP サンプルコード (Scala)Akka アクターを用いて実装された汎用 HTTP フレームワークです。Spray の後継です。コアモジュールである akka-http-core は 2016/2/17 に experimental が外れました。akka-http などのいくつかのサブモジュールは 2016/3/1 現在 experimental のままですが、基本的な
- Kestrel の使用例Kestrel は Message Queue (MQ) の実装のひとつです。一般に MQ はアプリケーション間やプロセス間、スレッド間で非同期に通信するために用いられます。メッセージの送信側は MQ に書き込めば受信側の応答を待たずに次の処理に非同期に進むことができます。Kestrel はわずか 2500 行程の Scala で実装されており JVM で動作します。MQ 自体はメモリ上に存在する...
- Android Activity ライフサイクルの様子を把握するための簡易サンプルコードAndroid アプリケーションのコンポーネントの一つである Activity についてライフサイクルの様子を把握するための簡易サンプルコードです。 The Activity Lifecycle [ライフサイクルの状態遷移図](https://developer.android.com/guide/components/