
本文档旨在指导开发者使用Spring Boot框架实现用户注册功能,并自动为新注册用户分配默认角色。我们将详细介绍如何配置数据模型、Repository、Service以及Controller,并提供完整的代码示例,帮助你快速构建安全可靠的用户认证系统。本文档将解决用户注册时数据无法保存到数据库的问题,重点在于RoleRepository的正确配置。
项目环境搭建首先,确保你已经安装了以下环境:
- JDK 8 或更高版本
- Maven
- MySQL 数据库
创建一个新的 Spring Boot 项目,并在 pom.xml 文件中添加以下依赖:
<dependencies>
<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.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
</dependency>
</dependencies> 数据库配置
在 application.properties 文件中配置数据库连接信息:
spring.datasource.url=jdbc:mysql://localhost:3306/auth?useSSL=false&serverTimezone=UTC spring.datasource.username=root spring.datasource.password=root spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.jpa.hibernate.ddl-auto=update spring.mvc.view.prefix=/WEB-INF/ spring.mvc.view.suffix=.jsp
请根据你的实际数据库配置进行修改。
创建数据模型创建 User 和 Role 实体类:
User.java:
package developer.andy.auth.models;
import java.util.Date;
import java.util.List;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.PrePersist;
import javax.persistence.PreUpdate;
import javax.persistence.Table;
import javax.persistence.Transient;
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String username;
private String password;
@Transient
private String confirm;
@Column(updatable=false)
private Date createdAt;
private Date updatedAt;
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(
name = "users_roles",
joinColumns = @JoinColumn(name = "user_id"),
inverseJoinColumns = @JoinColumn(name = "role_id"))
private List <Role> roles;
public User() {}
// Getters and Setters
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
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 getConfirm() {
return confirm;
}
public void setConfirm(String confirm) {
this.confirm = confirm;
}
public Date getCreatedAt() {
return createdAt;
}
public void setCreatedAt(Date createdAt) {
this.createdAt = createdAt;
}
public Date getUpdatedAt() {
return updatedAt;
}
public void setUpdatedAt(Date updatedAt) {
this.updatedAt = updatedAt;
}
public List<Role> getRoles() {
return roles;
}
public void setRoles(List<Role> roles) {
this.roles = roles;
}
@PrePersist
protected void onCreated() {
this.createdAt = new Date();
}
@PreUpdate
protected void onUpdate() {
this.updatedAt = new Date();
}
} Role.java:
package developer.andy.auth.models;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import java.util.List;
@Entity
@Table(name = "roles")
public class Role {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@ManyToMany(mappedBy = "roles")
private List<User> users;
public Role() {}
// Getters and Setters
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<User> getUsers() {
return users;
}
public void setUsers(List<User> users) {
this.users = users;
}
} 创建 Repository
创建 UserRepository 和 RoleRepository 接口:
UserRepository.java:
package developer.andy.auth.repositories;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
import developer.andy.auth.models.User;
@Repository
public interface UserRepository extends CrudRepository<User, Long> {
User findByUsername(String username);
} RoleRepository.java:
package developer.andy.auth.repositories;
import java.util.List;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
import developer.andy.auth.models.Role;
@Repository
public interface RoleRepository extends CrudRepository<Role, Long> { // Corrected data type to Long
List<Role> findAll();
List<Role> findByName(String name);
} 注意: RoleRepository 的泛型参数需要修改为 <Role, Long>,因为 Role 实体的主键类型是 Long。这是之前代码无法保存数据到数据库的关键原因。
HyperWrite
AI写作助手帮助你创作内容更自信
54
查看详情
创建 Service
创建 UserService 类:
package developer.andy.auth.services;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import developer.andy.auth.models.User;
import developer.andy.auth.repositories.RoleRepository;
import developer.andy.auth.repositories.UserRepository;
import java.util.List;
@Service
public class UserService {
private UserRepository userRepo;
private RoleRepository roleRepo;
private BCryptPasswordEncoder pwEncoder;
public UserService(UserRepository userRepo, RoleRepository roleRepo, BCryptPasswordEncoder pwEncoder) {
this.userRepo = userRepo;
this.roleRepo = roleRepo;
this.pwEncoder = pwEncoder;
}
// save with user role
public void saveWithUserRole(User user) {
user.setPassword(pwEncoder.encode(user.getPassword()));
List<Role> roles = roleRepo.findByName("ROLE_USER");
user.setRoles(roles);
userRepo.save(user);
}
// save with admin role
public void saveWithAdminRole(User user) {
user.setPassword(pwEncoder.encode(user.getPassword()));
List<Role> roles = roleRepo.findByName("ROLE_ADMIN");
user.setRoles(roles);
userRepo.save(user);
}
// find user by username
public User findByUsername(String username) {
return userRepo.findByUsername(username);
}
} 创建 Controller
创建 UserController 类:
package developer.andy.auth.controllers;
import javax.servlet.http.HttpSession;
import javax.validation.Valid;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import developer.andy.auth.models.User;
import developer.andy.auth.services.UserService;
@Controller
public class UserController {
private UserService userService;
public UserController(UserService userService) {
this.userService = userService;
}
@RequestMapping("/register")
public String register(@Valid @ModelAttribute("user") User user) {
return "register.jsp";
}
@PostMapping("/process")
public String process(@Valid @ModelAttribute("user") User user, BindingResult result, Model model, HttpSession session) {
if(result.hasErrors()) {
return "register.jsp";
}
userService.saveWithUserRole(user);
return "redirect:/login";
}
@RequestMapping("/login")
public String login() {
return "login.jsp";
}
} Spring Security 配置
创建 WebSecurityConfiguration 类:
package developer.andy.auth.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.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
public class WebSecurityConfiguration {
@Bean
public BCryptPasswordEncoder pwEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
protected SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/css/**", "/js/**", "/register").permitAll()
.anyRequest()
.authenticated()
.and()
.formLogin().loginPage("/login").permitAll()
.and()
.logout().permitAll();
return http.build();
}
} 创建JSP页面
创建 register.jsp 和 login.jsp 页面。
register.jsp:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Registration Page</title>
</head>
<body>
<h1>Register!</h1>
<p><form:errors path="user.*"/></p>
<form:form method="POST" action="/process" modelAttribute="user">
<p>
<form:label path="username">Username:</form:label>
<form:input path="username"/>
</p>
<p>
<form:label path="password">Password:</form:label>
<form:password path="password"/>
</p>
<p>
<form:label path="confirm">Confirm:</form:label>
<form:password path="confirm"/>
</p>
<input type="submit" value="Register!"/>
</form:form>
</body>
</html> login.jsp:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Login Page</title>
</head>
<body>
<h1>Login</h1>
<form method="POST" action="/login">
<div>
<label>Username:</label>
<input type="text" name="username">
</div>
<div>
<label>Password:</label>
<input type="password" name="password">
</div>
<input type="submit" value="Login">
</form>
</body>
</html> 初始化角色数据
为了保证程序正常运行,需要在数据库中预先创建角色数据。你可以使用 SQL 脚本或者在 Spring Boot 启动时初始化数据。
以下是一个使用 SQL 脚本初始化角色数据的例子:
INSERT INTO roles (name) VALUES ('ROLE_USER');
INSERT INTO roles (name) VALUES ('ROLE_ADMIN'); 总结与注意事项
通过以上步骤,你就可以实现用户注册并自动分配默认角色的功能了。 关键在于确保 RoleRepository 的泛型参数类型与 Role 实体的主键类型一致。
注意事项:
- 密码需要进行加密存储,这里使用了 BCryptPasswordEncoder。
- 需要处理密码和确认密码不一致的情况,可以在 User 实体类中添加校验注解。
- 需要对用户输入进行验证,防止 SQL 注入等安全问题。
- 实际项目中,还需要考虑用户权限管理、角色分配等更复杂的功能。
- 确保在数据库中预先创建了 ROLE_USER 和 ROLE_ADMIN 角色。
修改 RoleRepository 接口的定义,将 CrudRepository<Role, String> 修改为 CrudRepository<Role, Long> 解决了用户注册时数据无法保存到数据库的问题。 确保数据库中已经存在对应的角色数据,并正确配置了数据库连接信息。 通过以上步骤,你应该能够成功实现用户注册和角色分配的功能。
以上就是Spring Boot用户注册与角色分配:实战教程的详细内容,更多请关注知识资源分享宝库其它相关文章!
相关标签: css mysql word java html js go apache app ssl session tomcat Java sql spring spring boot String xml register 接口 泛型 数据库 jsp 大家都在看: MySQL多级关联表级联删除策略:解决外键约束冲突 解决 Spring Boot JPA 中 MySQL 数据检索空指针异常 解决JavaFX + MySQL登录验证失败问题:ResultSet使用详解 解决JDBC连接MySQL自动重连后数据库未选中问题 java怎样连接并操作MySQL数据库 java数据库编程的入门教程






发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。