Spring フレームワークによる Web アプリケーション開発で、ログイン処理を実装する際は Spring Security が便利です。ここでは特に、こちらのページに記載の Spring Boot で Web アプリケーションを開発する場合を対象とし、フォームによる ID/Password ログインを行うためのサンプルコードをまとめます。
公式ドキュメント
基本的な 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-starter-security
を設定します。spring-boot-starter-thymeleaf
は Thymeleaf の設定です。./gradlew dependencies
を実行すると spring-boot-starter-web
も依存先としてインストールされることが分かります。spring-boot-devtools
で開発時に便利な機能を利用できるようになります。
アノテーションの意味についてはこちらをご参照ください。
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);
}
}
今回のサンプルコードでは @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");
}
}
@EnableWebSecurity
アノテーションが設定されて WebSecurityConfigurerAdapter
を継承したクラスで Spring Security の既定の挙動をカスタマイズできます。ユーザー名が user でパスワードはアプリケーション起動時にログで確認できる Basic 認証が既定ですが、以下ではログインフォーム認証をユーザ名 user
パスワード password
で行うように変更しています。
パスに関する設定の意味はそれぞれ以下のとおりです。いずれも公式ドキュメントで更に詳細な設定が可能なことが確認できます。
/
と /home
は認証なしで表示できるように設定しています。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.
}
}
こちらのページで使い方をまとめた Thymeleaf を利用しています。xmlns:th="http://www.thymeleaf.org"
は IDE の警告表示を回避するための設定です。
ログインせずに表示できるホームページです。
<!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>
ログインが必要なページです。ホームページからリンクされています。ログアウトするためのフォームも設置されています。#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>
ユーザー名とパスワードを 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>
本ページでは簡単のため、Java ソースコードにハードコーディングされた auth.inMemoryAuthentication() を利用しました。実際にアプリケーションを開発する際はその他の認証方法を利用します。例えば LDAP を利用する場合は auth.ldapAuthentication() を設定します。具体的なサンプルコードはこちらのページをご参照ください。