9月2日

ログイン認証

プロジェクト名: tweeter
パッケージ名: jp.abc

pom.xmlにTymeleafとJPAとHSQLDBの依存関係を追加する。
Spring Boot のバージョンを2.1.4にする。

<?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.1.4.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>jp.abc</groupId>
	<artifactId>tweeter</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>tweeter</name>
	<description>Tweeter</description>

	<properties>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<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>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-thymeleaf</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-security</artifactId>
		</dependency>

		<dependency>
			<groupId>org.hsqldb</groupId>
			<artifactId>hsqldb</artifactId>
		</dependency>

	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

HSQLDBを起動するBATファイルを修正する。tweeter インスタンスを追加する。

cd C:\pleiades\hsqldb-2.4.1\hsqldb\lib
java -cp hsqldb.jar org.hsqldb.Server --database.0 db/tweeter --dbname.0 tweeter

application.properties にHSQLDBの設定を追加する。

spring.datasource.url=jdbc:hsqldb:hsql://localhost/tweeter
spring.datasource.username=sa
spring.datasource.password=
spring.datasource.driver-class-name=org.hsqldb.jdbc.JDBCDriver
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.HSQLDialect
spring.jpa.hibernate.ddl-auto=update

Spring Boot でJDBCを使ってユーザー登録・ユーザー認証する方法

4つのHTMLテンプレートを作成する。

index.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>トップページ</title>
</head>
<body>
    <h1>トップページ</h1>
    <a href="/mypage">マイページ</a>
</body>
</html>

mypage.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8" />
    <title>login</title>
</head>
<body>
    <h1>マイページ</h1>
    <form th:action="@{/logout}" method="post">
        <input type="submit" value="ログアウト" />
    </form>
</body>
</html>

login.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8" />
    <title>login</title>
</head>
<body>
    <div th:if="${param.error}">
        エラー: ユーザ名・パスワードが違います。
    </div>
    <form th:action="@{/login}" method="post">
        <div><label>ユーザ名: <input type="text" name="username"/> </label></div>
        <div><label>パスワード: <input type="password" name="password"/> </label></div>
        <div><input type="submit" value="ログイン"/></div>
    </form>
    <div><a href="/newuser">新規ユーザー登録</a></div>
    <a href="/">戻る</a>
</body>
</html>

newuser.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8" />
    <title>新規ユーザー登録</title>
</head>
<body>
    <h1>新規ユーザー登録</h1>
    <form th:action="@{/newuser}" method="post">
        <div><label>ユーザ名: <input type="text" name="username"/> </label></div>
        <div><label>パスワード: <input type="password" name="password"/> </label></div>
        <div><label>パスワード再入力: <input type="password" name="password2"/> </label></div>
        <div><input type="submit" value="登録"/></div>
    </form>
    <a href="/">戻る</a>
</body>
</html>

コントローラを作成する。
MyController.java

package jp.abc;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class MyController {
    @RequestMapping(value = "/")
    public String index() {
        return "index";
    }

    @RequestMapping(value = "/login")
    public String login() {
        return "login";
    }

    @RequestMapping(value = "/newuser")
    public String newuser() {
        return "newuser";
    }

    @RequestMapping(value = "/mypage")
    public String top() {
        return "mypage";
    }
}

WebSecurityConfig クラスを作成する。

package jp.abc;

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;

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter{
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
            .antMatchers("/", "/newuser").permitAll()
            .anyRequest().authenticated()
            .and()
            .formLogin()
            .loginPage("/login")
            .permitAll()
            .and()
            .logout()
            .permitAll();
    }
}

WebSecurityConfig にデータベース認証のコードを追加する。

package jp.abc;

import javax.sql.DataSource;

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.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.User.UserBuilder;

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter{
	@Autowired
	private DataSource dataSource;

	@Autowired
	public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
		UserBuilder users = User.withDefaultPasswordEncoder();
		auth
		.jdbcAuthentication()
		.dataSource(dataSource)
		.withDefaultSchema()
		.withUser(users.username("user").password("password").roles("USER"));
	}

	@Override
	protected void configure(HttpSecurity http) throws Exception {
		http.authorizeRequests()
		.antMatchers("/", "/newuser").permitAll()
		.anyRequest().authenticated()
		.and()
		.formLogin()
		.loginPage("/login")
		.permitAll()
		.and()
		.logout()
		.permitAll();
	}
}

このコードで起動すると、1度目は正常に起動するが、再起動すると例外が発生して起動できなくなる。
例外の原因が withDefaultScheme() と withUser() なので、その部分を削除する。

WebSecurityConfig.java

	@Autowired
	public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
		auth
		.jdbcAuthentication()
		.dataSource(dataSource);
	}

コントローラで新規ユーザー登録のPOSTメソッドを受け付けるようにする。

package jp.abc;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.User.UserBuilder;
import org.springframework.security.provisioning.JdbcUserDetailsManager;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

@Controller
public class MyController {
	@Autowired
	private JdbcUserDetailsManager userManager;

	@RequestMapping(value = "/")
	public String index() {
		return "index";
	}

	@RequestMapping(value = "/login")
	public String login() {
		return "login";
	}

	@RequestMapping(value = "/newuser", method = RequestMethod.GET)
	public String newuser() {
		return "newuser";
	}

	@RequestMapping(value = "/newuser", method = RequestMethod.POST)
	public String register(@RequestParam("username") String username,
			@RequestParam("password") String password) {
		UserBuilder users = User.withDefaultPasswordEncoder();
		userManager.createUser(users.username(username).password(password).roles("USER").build());
		return "login";
	}

	@RequestMapping(value = "/mypage")
	public String top() {
		return "mypage";
	}
}

この状態で起動しようとするとエラーが発生して起動に失敗する。

***************************
APPLICATION FAILED TO START
***************************

Description:

Field userManager in jp.abc.MyController required a bean of type 'org.springframework.security.provisioning.JdbcUserDetailsManager' that could not be found.

The injection point has the following annotations:
	- @org.springframework.beans.factory.annotation.Autowired(required=true)


Action:

Consider defining a bean of type 'org.springframework.security.provisioning.JdbcUserDetailsManager' in your configuration.

JdbcUserDetailManager のビーンを設定に用意しろと言われているので、その設定を追加する。

WebSecurityConfig.java

	@Bean
	public JdbcUserDetailsManager jdbcUserDetailsManager() throws Exception {
		JdbcUserDetailsManager jdbcUserDetailsManager = new JdbcUserDetailsManager();
		jdbcUserDetailsManager.setDataSource(dataSource);
		return jdbcUserDetailsManager;
	}

設定を追加した後に再起動すると、エラーなく起動できる。
ユーザー登録とログインもできるようになっていて、ログインすればマイページにアクセスできる。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください