ログイン認証
プロジェクト名: 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;
}
設定を追加した後に再起動すると、エラーなく起動できる。
ユーザー登録とログインもできるようになっていて、ログインすればマイページにアクセスできる。