Spring Boot用户注册与角色分配:实战教程(用户注册.实战.分配.角色.教程...)

wufei123 发布于 2025-09-24 阅读(13)

spring boot用户注册与角色分配:实战教程

本文档旨在指导开发者使用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 HyperWrite

AI写作助手帮助你创作内容更自信

HyperWrite54 查看详情 HyperWrite 创建 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数据库编程的入门教程

标签:  用户注册 实战 分配 

发表评论:

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