我想要创建一个登录界面
首先
Java没有像PHP的Laravel那样可以用一个命令创建登录功能模板的功能。如果只是要实现登录功能,可以在SpringBoot的Spring Security项目中引入,这样就可以提供具有固定用户名和密码的登录功能。但是,为了与数据库进行协作,需要一些相关知识。因此,在利用chatGPT(GPT4)创建登录功能时,我将记录这篇文章作为备忘录。
关于环境
-
- Javaのバージョン: 17
-
- Spring Bootのバージョン: 2.5.4
-
- MacOS
- Eclipse(IDE)
ChatGPT的知識基于2021年9月之前的信息,因此它在那个时刻执行的是最新版本的工作。
关于如何在Java中实现登录功能
在Java的框架(Spring Boot)中,有一个名为Spring Security的功能,它可以通过简单地将其引入项目来为项目添加登录功能。


引进Spring Security的方法
在多种方式中选择一种SpringBoot的引入方法。
如果要创建新项目。
在使用Eclipse创建新项目时,只需勾选依赖关系,Spring Security将自动设置项目的依赖关系。
依赖关系是调用特定功能的设置。
Spring Boot最初就包含了连接数据库、设置安全性和创建Web应用程序的功能,想要调用这些功能就需要设置依赖关系。

如果要添加到现有项目中
要在现有项目中添加Spring Security的依赖关系,需要编辑项目的构建工具(Maven或Gradle)的配置文件。
在创建项目时,Maven和Gradle会有一个被配置。
如果项目中存在build.gradle文件,则为Gradle;
如果存在pom.xml文件,则为Maven。
在使用Gradle的情况下
-
- 打开项目的构建文件(build.gradle)。
-
- 在dependencies部分中添加Spring Security的依赖关系。
- 保存文件。
dependencies {
// 他の依存関係の設定
implementation 'org.springframework.boot:spring-boot-starter-security'
}
-
- 为了更新依存关系,执行构建工具。
-
- 在终端中切换到项目的根目录。
- 执行以下命令。
gradle build
对于Maven
-
- 打开项目的pom.xml文件(如使用Maven)。
在部分内,添加Spring Security的依赖关系。请添加以下依赖关系的代码块。
<dependencies>
<!-- 他の依存関係の設定 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
</dependencies>
-
- 请保存文件并更新依赖关系的构建工具。
在项目的根目录中执行以下命令。
mvn clean install
這將在項目中添加Spring Security的依賴關係。
关于登录信息(账户)
如果在使用Spring Security时已经达到可以显示HTML的阶段,那么当访问该URL时将会显示登录页面。然而,由于尚未与数据库进行协作,因此只能使用以下固定的帐户来登录。
-
- user名:user
- パスワード:コンソールに表示されるランダムな文字列
密码需要通过哈希化的随机数显示在控制台上,因此需要将其复制并粘贴。


与数据库的连接
在SpringBoot中,可以通过与数据库连接来使用非固定账户,为此需要对项目和数据库进行各种准备工作。
关于桌子
通常登录界面所需的信息是用户名和密码,因此表格信息如下:
表名:用户
只要有用户名(username)和密码(password)存在,即使登录界面上还包含与之无关的电子邮件列(email),也不会有问题。
保存的数据需要进行哈希化。
正如下图所示,密码被转换为符号和数字的一系列字符。总之,Spring Security推荐将密码进行哈希处理后保存,数据库中存储的密码默认情况下是无法使用未经哈希处理的。

简而言之,无法通过非红框以外的账号登录到图像帐户。
顺便提一下,红框中的密码是以root4和root5为关键字进行哈希处理的。关于如何进行哈希处理并保存的方法将在后面的说明中进行解释,但实际上是通过准备新账号创建界面并在那里创建帐户的方法。
密码哈希化由Spring Security执行
Spring Security 中有一个功能叫密码编码器,可以对密码进行转换,简化密码的哈希化和验证(匹配确认)等操作。哈希化是一种将密码加密并将原始密码转换为不可恢复形式的方法。
使用密码编码器需要
密码编码器是一个接口,它包含了实现具体哈希算法的方法,为了使用它,需要在项目中准备一个专门的类(有关代码等详细信息请参考后述)。
在试用登录功能之前
正如前面所述,为了测试使用Spring Security实现的登录功能,需要一个经过哈希处理的密码。因此,即使在数据库表中提前以明文保存了用户名和密码,也不能使用该账户进行登录。因此,为了测试登录功能,还需要实现账户的新建功能。
所需项目的最低文件
要使用Spring Security来执行登录功能和新建账户页面,需要以下一系列文件。
文件名和目录名没有规定,以下是一些常见的名称。
.
├── src
│ ├── main
│ │ ├── java
│ │ │ ├── com
│ │ │ │ ├── example
│ │ │ │ │ ├── controller
│ │ │ │ │ │ ├── LoginController.java
│ │ │ │ │ │ └── RegisterController.java
│ │ │ │ │ ├── model
│ │ │ │ │ │ ├── User.java
│ │ │ │ │ │ └── UserDto.java
│ │ │ │ │ ├── service
│ │ │ │ │ │ ├── UserService.java
│ │ │ │ │ │ └── UserServiceImpl.java
│ │ │ │ │ └── config
│ │ │ │ │ ├── SecurityConfig.java
│ │ │ │ │ └── PasswordEncoderConfig.java
│ │ ├── resources
│ │ │ ├── templates
│ │ │ │ ├── login.html
│ │ │ │ └── register.html
│ │ │ └── application.properties
│ ├── test
├── build.gradle (またはpom.xml、もしMavenを使用している場合)
└── ...
模型类 (User.java)
用于表示用户数据的类。根据情况,它也被称为实体类或数据传输对象(DTO)。在这里,例如,如果数据库中存在Users表,则可以创建一个名为User.java的文件,并准备一个变量来存储用户名和密码,从而将表与Java关联起来。
数据访问对象(UserRepository.java)
用于保存和检索用户数据的接口。可以使用Spring Data JPA来简化数据库操作。JPA是将表列和Java变量进行映射的功能。使用它需要像Spring Security一样配置依赖关系。
服务类 (UserService.java)
实现与用户相关的业务逻辑的类。例如,在此处创建新用户注册和现有用户搜索等处理。
控制器类(LoginController.java)
用于处理HTTP请求的类。处理登录和注册请求,显示适当的视图并执行相应的方法。
视图文件(login.html,register.html)
用于向用户显示登录表单和新用户注册表单的HTML模板。
安全配置类(SecurityConfig.java)
定义了Spring Security配置的类。设置登录机制、密码编码、授权规则等。
数据库连接设置
数据库连接信息(application.properties)
把与互联数据库相关的URL和端口号等信息,写在application.properties文件里。

因此,连接设置如下所示。
# データベースに接続するためのURLを設定します。ここではMySQLのデータベース「LibraryManagementSystem」に接続するためのURLを指定しています。
spring.datasource.url=jdbc:mysql://localhost:8889/LibraryManagementSystem?useSSL=false&serverTimezone=UTC
# データベースに接続するためのユーザー名を設定します。ここでは'root'というユーザー名を指定しています。
spring.datasource.username=root
# データベースに接続するためのパスワードを設定します。ここでは'root'というパスワードを指定しています。
spring.datasource.password=root
# データベースに接続するためのドライバークラス名を設定します。ここではMySQL用のドライバーを指定しています。
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# データベースとエンティティの間のテーブル作成・更新・削除の動作を制御します。ここでは何もしないことを示す'none'を指定しています。
spring.jpa.hibernate.ddl-auto=none
# 実行されるSQLをログに出力するかどうかを制御します。ここでは出力するために'true'を指定しています。
spring.jpa.show-sql=true
# 使用するデータベースの種類に合わせたSQLを生成するための方言(Dialect)を指定します。ここではMySQL用の方言を指定しています。
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
# SQLをログに出力する際に整形するかどうかを制御します。ここでは整形するために'true'を指定しています。
spring.jpa.properties.hibernate.format_sql=true
# Springのログレベルを設定します。ここではDEBUGレベルのログを出力するように設定しています。
logging.level.org.springframework=DEBUG
不仅包括连接设置,还包括将SQL日志输出到控制台等设置,并不是所有的代码都是必需的。
文件位置(结构图)
- application.properties
project-directory # プロジェクトのルートディレクトリ
├── src # ソースコードを格納するディレクトリ
│ ├── main # メインのソースコードとリソースを格納するディレクトリ
│ │ ├── java # Javaソースコードを格納するディレクトリ
│ │ │ └── com # ここからパッケージ構造が始まる
│ │ │ └── example # 例えば 'com.example' パッケージ
│ │ │ └── ... # その他のパッケージとJavaクラス
│ │ └── resources # リソースファイルを格納するディレクトリ
│ │ ├── static # 静的リソースを格納するディレクトリ(CSSやJavaScriptファイルなど)
│ │ ├── templates # Thymeleafなどのテンプレートエンジンによるビューファイルを格納するディレクトリ
│ │ └── application.properties # Spring Bootの設定を格納するファイル
│ └── test # テストのソースコードとリソースを格納するディレクトリ
└── ... # その他のファイルとディレクトリ(例:pom.xml, .gitignore, README.mdなど)
所需的文件(代码)
构图(示例)
project-directory # プロジェクトのルートディレクトリ
├── src # ソースコードを格納するディレクトリ
│ ├── main # メインのソースコードとリソースを格納するディレクトリ
│ │ ├── java # Javaソースコードを格納するディレクトリ
│ │ │ └── com # ここからパッケージ構造が始まる
│ │ │ └── example # 例えば 'com.example' パッケージ
│ │ │ ├── LibraryManagementSystemApplication.java # Spring Bootアプリケーションのエントリーポイント
│ │ │ ├── controller # controller パッケージ
│ │ │ │ ├── LoginController.java # ログインに関する処理を行うコントローラ
│ │ │ │ └── RegisterController.java # 登録に関する処理を行うコントローラ
│ │ │ ├── model # model パッケージ
│ │ │ │ ├── User.java # Userエンティティのモデルクラス
│ │ │ │ └── UserDto.java # Userエンティティに関するデータ転送オブジェクト (DTO)
│ │ │ ├── repository # repository パッケージ
│ │ │ │ └── UserRepository.java # Userエンティティに関するリポジトリインターフェース
│ │ │ └── service # service パッケージ
│ │ │ ├── UserPrincipal.java # ユーザーの認証情報を保持するクラス
│ │ │ └── UserService.java # Userエンティティに関するサービスクラス
│ │ └── resources # リソースファイルを格納するディレクトリ
│ └── test # テストのソースコードとリソースを格納するディレクトリ
└── ... # その他のファイルとディレクトリ(例:pom.xml, .gitignore, README.mdなど)
有时根据规范,可能将”model”目录称为”entity”目录。
图书馆管理系统应用程序.java
由于此项目名为LibraryManagementSystem,因此文件名中附有项目名。
在Spring Boot应用程序的主类中,有一个main方法作为应用程序的入口点。在main方法中调用SpringApplication.run来启动应用程序。@SpringBootApplication注解表示这个类是一个Spring Boot应用程序。
package com.example; // このファイルが属するパッケージ(フォルダ)
// 必要なクラスをインポートします
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication // Spring Bootアプリケーションであることを示します
public class LibraryManagementSystemApplication { // アプリケーションのメインクラス
public static void main(String[] args) { // Javaアプリケーションのエントリーポイント(最初に実行されるメソッド)
SpringApplication.run(LibraryManagementSystemApplication.class, args); // Spring Bootアプリケーションを起動します
}
}
用户.java
将用户表(User Table)与Java变量(字段)相关联
package com.example.model; // このファイルが属するパッケージ(フォルダ)
// 以下の部分はデータベースとのやり取りに必要な情報を持つためのものです。
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity // これはデータベースのテーブルを表しています
@Table(name = "Users") // このクラスが対応するテーブルの名前は "Users" です
public class User {
@Id // これが各ユーザを一意に識別するためのIDとなります
@GeneratedValue(strategy = GenerationType.IDENTITY) // IDは自動的に増加します
@Column(name = "id") // データベースに合わせてカラム名を修正
private Integer id;
@Column(name = "username", nullable = false, unique = true) // "username" カラム。各ユーザーのユーザー名を表します。同じ名前のユーザーは存在できません
private String username;
@Column(name = "password", nullable = false) // "password" カラム。ユーザーのパスワードを表します
private String password;
@Column(name = "email", nullable = false, unique = true) // "email" カラム。ユーザーのメールアドレスを表します。同じメールアドレスのユーザーは存在できません
private String email;
// 以下は各値を取得するためのメソッド(ゲッター)です。
public Integer getId() {
return this.id;
}
public String getUsername() {
return this.username;
}
public String getPassword() {
return this.password;
}
public String getEmail() {
return this.email;
}
// 以下は各値を設定するためのメソッド(セッター)です。
public void setId(Integer id) {
this.id = id;
}
public void setUsername(String username) {
this.username = username;
}
public void setPassword(String password) {
this.password = password;
}
public void setEmail(String email) {
this.email = email;
}
}
UserDto.java的意思是Java类文件UserDto。
这是一个用来存储用户输入数据的类。用户在表单中输入的数据将被转换为此类的实例,并在应用程序中使用。@NotEmpty注释用于输入值检查,以确保目标字段不为空。这样可以防止用户发送空白数据。
package com.example.model; // このファイルが属するパッケージ(フォルダ)
// 入力チェックをするためのツールをインポートしています。
import javax.validation.constraints.NotEmpty;
public class UserDto { // ユーザーのデータを扱うためのクラス
@NotEmpty // ユーザー名は空であってはならないというルール
private String username; // ユーザー名を保存するための場所
@NotEmpty // パスワードは空であってはならないというルール
private String password; // パスワードを保存するための場所
@NotEmpty // メールアドレスは空であってはならないというルール
private String email; // メールアドレスを保存するための場所
// 以下は各値を取得するためのメソッド(ゲッター)です。
public String getUsername() {
return username; // ユーザー名を返す
}
public void setUsername(String username) {
this.username = username; // ユーザー名を設定する
}
public String getPassword() {
return password; // パスワードを返す
}
public void setPassword(String password) {
this.password = password; // パスワードを設定する
}
public String getEmail() {
return email; // メールアドレスを返す
}
public void setEmail(String email) {
this.email = email; // メールアドレスを設定する
}
}
用户存储库.java
这个接口定义了一个用于对User实体进行数据库操作的仓库。通过继承JpaRepository,它可以自动提供各种数据库操作,例如保存、更新、删除和查询等。findByUsername方法是一个用于根据指定的用户名搜索用户的方法,Spring Data JPA会自动生成其实现。
package com.example.repository; // このファイルが属するパッケージ(フォルダ)
// 必要なツールをインポートしています
import org.springframework.data.jpa.repository.JpaRepository;
// Userクラスを使うためにインポートしています
import com.example.model.User;
// UserRepositoryというインターフェースを作成します。JpaRepositoryを拡張して、UserオブジェクトとそれらのIDとしてLong型を扱えるようにします。
public interface UserRepository extends JpaRepository<User, Long> {
// ユーザー名でユーザーを探すメソッド。ユーザー名をパラメータとして渡すと、そのユーザー名を持つユーザーをデータベースから探して返します。
User findByUsername(String username);
}
用户主要.java
实现了Spring Security的UserDetails接口,在认证(登录)时将被Spring Security使用。它保存了用户的信息(用户名、密码、权限等),并提供这些信息。
package com.example.service; // このファイルが属するパッケージ(フォルダ)
// 必要なツールをインポートしています
import java.util.Collection;
import java.util.Collections;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
// Userクラスを使うためにインポートしています
import com.example.model.User;
// UserDetailsインターフェースを実装したUserPrincipalというクラスを作成します。これはSpring Securityでユーザー情報を扱うためのクラスです。
public class UserPrincipal implements UserDetails {
private User user; // Userオブジェクトを保持します。
// コンストラクタでUserオブジェクトを受け取り、それをこのクラスのuserにセットします。
public UserPrincipal(User user) {
this.user = user;
}
// ユーザーに与えられる権限を返します。ここでは全てのユーザーに"USER"という権限を与えています。
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return Collections.singleton(new SimpleGrantedAuthority("USER"));
}
// Userオブジェクトのパスワードを返します。
@Override
public String getPassword() {
return user.getPassword();
}
// Userオブジェクトのユーザー名を返します。
@Override
public String getUsername() {
return user.getUsername();
}
// アカウントが有効期限切れでないことを示すために、常にtrueを返します。
@Override
public boolean isAccountNonExpired() {
return true;
}
// アカウントがロックされていないことを示すために、常にtrueを返します。
@Override
public boolean isAccountNonLocked() {
return true;
}
// 資格情報(ここではパスワード)が有効期限切れでないことを示すために、常にtrueを返します。
@Override
public boolean isCredentialsNonExpired() {
return true;
}
// アカウントが有効であることを示すために、常にtrueを返します。
@Override
public boolean isEnabled() {
return true;
}
}
用户服务.java
package com.example.service; // このファイルが属するパッケージ(フォルダ)
// 必要なクラスをインポートします
import javax.transaction.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import com.example.model.User;
import com.example.model.UserDto;
import com.example.repository.UserRepository;
@Service // このクラスがサービス層のクラスであることを示します
public class UserService implements UserDetailsService { // UserDetailsServiceインターフェースを実装しています
@Autowired // Springが自動的にUserRepositoryの実装を注入します
private UserRepository userRepository;
@Autowired // Springが自動的にPasswordEncoderの実装を注入します
private PasswordEncoder passwordEncoder;
@Override // UserDetailsServiceインターフェースのメソッドを上書きします
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findByUsername(username); // ユーザー名でユーザーを検索します
if (user == null) {
throw new UsernameNotFoundException("User not found"); // ユーザーが見つからない場合、例外をスローします
}
return new UserPrincipal(user); // ユーザーが見つかった場合、UserPrincipalを作成し返します
}
//新たにメソッドを追加します
public User findByUsername(String username) {
return userRepository.findByUsername(username); // ユーザー名でユーザーを検索し返します
}
@Transactional // トランザクションを開始します。メソッドが終了したらトランザクションがコミットされます。
public void save(UserDto userDto) {
// UserDtoからUserへの変換
User user = new User();
user.setUsername(userDto.getUsername());
// パスワードをハッシュ化してから保存
user.setPassword(passwordEncoder.encode(userDto.getPassword()));
user.setEmail(userDto.getEmail());
// データベースへの保存
userRepository.save(user); // UserRepositoryを使ってユーザーをデータベースに保存します
}
}
安全配置.java
这个类是用来定义Spring Security的配置。每个方法提供了与安全相关的配置。包括密码哈希化、访问控制、登录页面设置、登出设置等。
package com.example.Config; // このファイルが属するパッケージ(フォルダ)
// 必要なクラスやインターフェースをインポートします
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.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
@Configuration // このクラスは設定クラスであることを示します
@EnableWebSecurity // Webセキュリティを有効にすることを示します
public class SecurityConfig { // セキュリティ設定のクラス
@Bean // このメソッドの返り値をSpringのBeanとして登録します
public PasswordEncoder passwordEncoder() { // パスワードエンコーダー(パスワードのハッシュ化)を提供するメソッド
return new BCryptPasswordEncoder(); // パスワードをBCrypt方式でハッシュ化するエンコーダーを返します
}
@Bean // このメソッドの返り値をSpringのBeanとして登録します
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { // セキュリティフィルタチェーンを定義するメソッド
http
.authorizeRequests(authorizeRequests -> // 認証リクエストを設定します
authorizeRequests
.antMatchers("/login", "/register").permitAll() // "/login"と"/register"へのリクエストは認証なしで許可します
.anyRequest().authenticated() // それ以外の全てのリクエストは認証が必要です
)
.formLogin(formLogin -> // フォームベースのログインを設定します
formLogin
.loginPage("/login") // ログインページのURLを設定します
.permitAll() // ログインページは認証なしで許可します
)
.logout(logout -> // ログアウトを設定します
logout
.logoutRequestMatcher(new AntPathRequestMatcher("/logout")) // ログアウトのリクエストURLを設定します
);
return http.build(); // 上記の設定を反映してHttpSecurityオブジェクトをビルドします
}
// 他のセキュリティ設定が必要な場合は、ここに追加します
}
登录控制器.java
Web控制器用于处理用户的HTTP请求并返回适当的响应。@Controller注解表示这个类是一个Web控制器。@GetMapping注解指定了处理特定URL的GET请求的方法。每个方法的返回值可以是要显示的HTML页面名称或重定向的URL。
package com.example.controller; // このファイルが属するパッケージ(フォルダ)
// 必要なクラスをインポートします
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller // このクラスがWebコントローラーであることを示します
public class LoginController {
@GetMapping("/login") // "/login"というURLに対するGETリクエストを処理します
public String login() {
return "login"; // login.htmlを表示します
}
@GetMapping("/") // ルートURL ("/") に対するGETリクエストを処理します
public String redirectToIndex() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); // 現在のユーザーの認証情報を取得します
if (authentication != null && authentication.isAuthenticated()) { // ユーザーがログインしている場合
return "redirect:/index"; // "/index"にリダイレクトします
}
return "redirect:/login"; // ユーザーがログインしていない場合、"/login"にリダイレクトします
}
@GetMapping("/index") // "/index"というURLに対するGETリクエストを処理します
public String index() {
return "index"; // index.htmlを表示します
}
}
注册控制器.java
这是一个处理用户注册请求的Web控制器。registerForm()方法用于显示注册表单。register(@ModelAttribute UserDto userDto)方法用于处理用户注册。如果用户名已存在,则返回注册页面。如果用户名不存在,则保存新用户并重定向到登录页面。
package com.example.controller; // このファイルが属するパッケージ(フォルダ)
// 必要なクラスをインポートします
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.servlet.ModelAndView;
import com.example.model.User;
import com.example.model.UserDto;
import com.example.service.UserService;
@Controller // このクラスがWebコントローラーであることを示します
public class RegisterController {
// Spring が自動的に UserService の実装を注入します
@Autowired
private UserService userService;
@GetMapping("/register") // "/register"というURLに対するGETリクエストを処理します
public ModelAndView registerForm() {
ModelAndView mav = new ModelAndView(); // ModelAndViewオブジェクトを作成します
mav.addObject("user", new UserDto()); // 新しいUserDtoオブジェクトを"ユーザー"という名前で追加します
mav.setViewName("register"); // 表示するビュー(HTMLファイル)の名前を"register"に設定します
return mav; // ModelAndViewオブジェクトを返します
}
@PostMapping("/register") // "/register"というURLに対するPOSTリクエストを処理します
public String register(@ModelAttribute UserDto userDto) {
User existing = userService.findByUsername(userDto.getUsername()); // ユーザー名で既存のユーザーを検索します
if(existing != null){
// ユーザーが既に存在する場合の処理
return "register"; // ユーザーが存在するため、再度登録画面を表示します
}
userService.save(userDto); // ユーザーが存在しない場合、新しいユーザーを保存します
return "login"; // 登録が成功した場合、ログイン画面を表示します
}
}
HTML是一种用于创建网页的标记语言。
这次限定在以下的画面上。
-
- ログイン画面 (login.html)
新規アカウント作成画面 (register.html)
ホーム画面 (index.html)
文件结构图
LibraryManagementSystem
├── src
│ ├── main
│ │ └── resources
│ │ └── templates
│ │ ├── login.html
│ │ ├── register.html
│ │ └── index.html
└── ...
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Login</title>
</head>
<body>
<div th:if="${param.error}">
<p>Invalid username and password.</p>
</div>
<div th:if="${param.logout}">
<p>You have been logged out.</p>
</div>
<form th:action="@{/login}" method="post">
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}"/>
<div>
<label>Username: </label>
<input type="text" name="username" required/>
</div>
<div>
<label>Password: </label>
<input type="password" name="password" required/>
</div>
<button type="submit">Login</button>
</form>
<p>
Don't have an account? <a th:href="@{/register}">Register</a> <!-- 新規アカウント作成ページへのリンクを追加 -->
</p>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>テスト</h1>
</body>
</html>
【重要】关于表单数据的发送(CSRF)
在Spring Boot的Spring Security中,默认启用了CSRF(跨站请求伪造)防护。这是为了保护Web应用程序免受CSRF攻击。
具体来说,在使用表单以POST方式提交数据时,还会同时发送一个特殊的值,即CSRF令牌。服务器端会确认这个CSRF令牌是否正确,如果不正确,服务器会拒绝该请求。这样可以防止用户进行意外的操作。
另外,尽管可以禁用CSRF防护措施,但这样做会使网络应用程序易受CSRF攻击,因此通常不推荐禁用。
CSRF攻击是指跨站请求伪造的攻击方式。
恶意网站在用户登录的另一个网站上进行操作。用户可能在不知情的情况下,被篡改或删除信息。
其实是想表达什么呢?
由于CSRF(跨站请求伪造)防护措施,在指定发送数据的目标地址时,通信被服务器阻断,导致无法将数据传递到数据库,从而无法注册新账户。
<form action="/register" method="post">
在实际上使用浏览器操作时,由于可以部分地发送数据,所以不会在控制台中产生错误。
然而,由于账户没有被添加到数据库中,所以这是一个原因不太容易理解的原因之一。
关于表单数据的目标地址(CSRF防护)
如果禁用默认设置的CSRF防护功能,可以在常规的发送目标上发送请求,但不建议这样做。
只需要一种选项:
通过以下方式,您可以向数据库发送要添加的帐户,而无需对CSRF功能进行通信阻碍。
<html xmlns:th="http://www.thymeleaf.org">
th:action="@{/somepath}" のように使う
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Register</title>
</head>
<body>
<h2>Register</h2>
<form th:action="@{/register}" method="post">
<label for="username">Username:</label><br>
<input type="text" id="username" name="username" required><br>
<label for="password">Password:</label><br>
<input type="password" id="password" name="password" required><br>
<label for="email">Email:</label><br>
<input type="email" id="email" name="email" required><br>
<input type="submit" value="Submit">
</form>
</body>
</html>
通过这样做,账户信息将被正确地发送到数据库,并且可以添加账户。
所添加账户的密码将由SecurityConfig类进行哈希处理并注册。




GitHub (Chinese: GitHub)
后记
这次创建的文件彼此紧密相连,如果有一个文件缺失,就会在某处发生错误,只有当全部齐备时才能避免错误。此外,使用的SpringBoot、Java和Spring Security的版本也会导致错误的发生。或许这是很自然的事情,但因为无法解决Eclipse中显示的错误而感到困扰,所以我觉得有必要记住这个原因。