3.3 用户注册

This commit is contained in:
zhangsan 2025-03-03 13:30:47 +08:00
parent e911d4c912
commit 3ff8188dd8
12 changed files with 380 additions and 0 deletions

View File

@ -41,6 +41,11 @@
<artifactId>knife4j-openapi2-spring-boot-starter</artifactId> <artifactId>knife4j-openapi2-spring-boot-starter</artifactId>
<version>4.4.0</version> <version>4.4.0</version>
</dependency> </dependency>
<!--密码BCrypt加密 -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-crypto</artifactId>
</dependency>
<dependency> <dependency>
<groupId>com.mysql</groupId> <groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId> <artifactId>mysql-connector-j</artifactId>

23
sql/create_table.sql Normal file
View File

@ -0,0 +1,23 @@
-- 创建库
create database if not exists `smile-picture`;
-- 使用库
use `smile-picture`;
-- 用户表
create table if not exists user
(
id bigint auto_increment comment 'id' primary key,
user_account varchar(256) not null comment '账号',
user_password varchar(512) not null comment '密码',
user_name varchar(256) null comment '用户昵称',
user_avatar varchar(1024) null comment '用户头像',
user_profile varchar(512) null comment '用户简介',
user_role varchar(256) default 'user' not null comment '用户角色user/admin',
edit_time datetime default CURRENT_TIMESTAMP not null comment '编辑时间',
create_time datetime default CURRENT_TIMESTAMP not null comment '创建时间',
update_time datetime default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '更新时间',
is_delete tinyint default 0 not null comment '是否删除',
UNIQUE KEY uk_userAccount (user_account),
INDEX idx_userName (user_name)
) comment '用户' collate = utf8mb4_unicode_ci;

View File

@ -1,9 +1,11 @@
package edu.whut.smilepicturebackend; package edu.whut.smilepicturebackend;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication @SpringBootApplication
@MapperScan("edu.whut.smilepicturebackend.mapper")
public class SmilePictureBackendApplication { public class SmilePictureBackendApplication {
public static void main(String[] args) { public static void main(String[] args) {

View File

@ -0,0 +1,13 @@
package edu.whut.smilepicturebackend.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
@Configuration
public class SecurityConfig {
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder(12); // 10 是强度
}
}

View File

@ -0,0 +1,34 @@
package edu.whut.smilepicturebackend.controller;
import edu.whut.smilepicturebackend.common.BaseResponse;
import edu.whut.smilepicturebackend.common.ResultUtils;
import edu.whut.smilepicturebackend.exception.ErrorCode;
import edu.whut.smilepicturebackend.exception.ThrowUtils;
import edu.whut.smilepicturebackend.model.dto.UserRegisterRequest;
import edu.whut.smilepicturebackend.service.UserService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/user")
@RequiredArgsConstructor
public class UserController {
private final UserService userService;
/**
* 用户注册
*/
@PostMapping("/register")
public BaseResponse<Long> userRegister(@RequestBody UserRegisterRequest userRegisterRequest) {
ThrowUtils.throwIf(userRegisterRequest == null, ErrorCode.PARAMS_ERROR);
String userAccount = userRegisterRequest.getUserAccount();
String userPassword = userRegisterRequest.getUserPassword();
String checkPassword = userRegisterRequest.getCheckPassword();
long result = userService.userRegister(userAccount, userPassword, checkPassword);
return ResultUtils.success(result);
}
}

View File

@ -0,0 +1,18 @@
package edu.whut.smilepicturebackend.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import edu.whut.smilepicturebackend.model.entity.User;
/**
* @author 张三
* @description 针对表user(用户)的数据库操作Mapper
* @createDate 2025-06-05 17:43:52
*/
public interface UserMapper extends BaseMapper<User> {
}

View File

@ -0,0 +1,29 @@
package edu.whut.smilepicturebackend.model.dto;
import lombok.Data;
import java.io.Serializable;
/**
* 用户注册请求
*/
@Data
public class UserRegisterRequest implements Serializable {
private static final long serialVersionUID = -1321880859645675653L;
/**
* 账号
*/
private String userAccount;
/**
* 密码
*/
private String userPassword;
/**
* 确认密码
*/
private String checkPassword;
}

View File

@ -0,0 +1,75 @@
package edu.whut.smilepicturebackend.model.entity;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* 用户
* @TableName user
*/
@TableName(value ="user")
@Data
public class User implements Serializable {
/**
* id
*/
@TableId(type = IdType.ASSIGN_ID)
private Long id;
/**
* 账号
*/
private String userAccount;
/**
* 密码
*/
private String userPassword;
/**
* 用户昵称
*/
private String userName;
/**
* 用户头像
*/
private String userAvatar;
/**
* 用户简介
*/
private String userProfile;
/**
* 用户角色user/admin
*/
private String userRole;
/**
* 编辑时间
*/
private Date editTime;
/**
* 创建时间
*/
private Date createTime;
/**
* 更新时间
*/
private Date updateTime;
/**
* 是否删除
*/
@TableLogic //标记逻辑删除字段
private Integer isDelete;
@TableField(exist = false)
private static final long serialVersionUID = 1L;
}

View File

@ -0,0 +1,42 @@
package edu.whut.smilepicturebackend.model.enums;
import cn.hutool.core.util.ObjUtil;
import lombok.Getter;
/**
* 用户角色枚举
*/
@Getter
public enum UserRoleEnum {
USER("用户", "user"),
VIP("会员", "vip"),
ADMIN("管理员", "admin");
private final String text;
private final String value;
UserRoleEnum(String text, String value) {
this.text = text;
this.value = value;
}
/**
* 根据 value 获取枚举
*
* @param value 枚举值的 value
* @return 枚举值
*/
public static UserRoleEnum getEnumByValue(String value) {
if (ObjUtil.isEmpty(value)) {
return null;
}
for (UserRoleEnum userRoleEnum : UserRoleEnum.values()) {
if (userRoleEnum.value.equals(value)) {
return userRoleEnum;
}
}
return null;
}
}

View File

@ -0,0 +1,30 @@
package edu.whut.smilepicturebackend.service;
import com.baomidou.mybatisplus.extension.service.IService;
import edu.whut.smilepicturebackend.model.entity.User;
/**
* @author 张三
* @description 针对表user(用户)的数据库操作Service
* @createDate 2025-06-05 17:43:52
*/
public interface UserService extends IService<User> {
/**
* 用户注册
*
* @param userAccount 用户账户
* @param userPassword 用户密码
* @param checkPassword 校验密码
* @return 新用户 id
*/
long userRegister(String userAccount, String userPassword, String checkPassword);
/**
* 获取加密后的密码
*
* @param userPassword
* @return
*/
String getEncryptPassword(String userPassword);
}

View File

@ -0,0 +1,86 @@
package edu.whut.smilepicturebackend.service.impl;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import edu.whut.smilepicturebackend.exception.BusinessException;
import edu.whut.smilepicturebackend.exception.ErrorCode;
import edu.whut.smilepicturebackend.model.entity.User;
import edu.whut.smilepicturebackend.model.enums.UserRoleEnum;
import edu.whut.smilepicturebackend.service.UserService;
import edu.whut.smilepicturebackend.mapper.UserMapper;
import lombok.RequiredArgsConstructor;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
/**
* @author 张三
* @description 针对表user(用户)的数据库操作Service实现
* @createDate 2025-06-05 17:43:52
*/
@Service
@RequiredArgsConstructor
public class UserServiceImpl extends ServiceImpl<UserMapper, User>
implements UserService{
private final BCryptPasswordEncoder passwordEncoder;
/**
* 用户注册
*
* @param userAccount 用户账户
* @param userPassword 用户密码
* @param checkPassword 校验密码
* @return
*/
@Override
public long userRegister(String userAccount, String userPassword, String checkPassword) {
// 1. 校验参数
if (StrUtil.hasBlank(userAccount, userPassword, checkPassword)) {
throw new BusinessException(ErrorCode.PARAMS_ERROR, "参数为空");
}
if (userAccount.length() < 4) {
throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户账号过短");
}
if (userPassword.length() < 8 || checkPassword.length() < 8) {
throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户密码过短");
}
if (!userPassword.equals(checkPassword)) {
throw new BusinessException(ErrorCode.PARAMS_ERROR, "两次输入的密码不一致");
}
// 2. 检查用户账号是否和数据库中已有的重复
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("userAccount", userAccount);
long count = this.baseMapper.selectCount(queryWrapper);
if (count > 0) {
throw new BusinessException(ErrorCode.PARAMS_ERROR, "账号重复");
}
// 3. 密码一定要加密
String encryptPassword = getEncryptPassword(userPassword);
// 4. 插入数据到数据库中
User user = new User();
user.setUserAccount(userAccount);
user.setUserPassword(encryptPassword);
user.setUserName("无名");
user.setUserRole(UserRoleEnum.USER.getValue());
boolean saveResult = this.save(user);
if (!saveResult) {
throw new BusinessException(ErrorCode.SYSTEM_ERROR, "注册失败,数据库错误");
}
return user.getId();
}
/**
* 获取加密后的密码
*
* @param userPassword 用户密码
* @return 加密后的密码
*/
@Override
public String getEncryptPassword(String userPassword) {
return passwordEncoder.encode(userPassword);
// // 加盐混淆密码
// final String SALT = "smile12306";
// return DigestUtils.md5DigestAsHex((SALT + userPassword).getBytes());
}
}

View File

@ -0,0 +1,23 @@
package edu.whut.smilepicturebackend.utils;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
//BCrypt加密工具类不如Bean注入效率更高已废弃
public class PasswordUtils {
private static final BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
/**
* 加密密码
*/
public static String encode(String rawPassword) {
return encoder.encode(rawPassword);
}
/**
* 校验密码是否匹配
*/
public static boolean matches(String rawPassword, String encodedPassword) {
return encoder.matches(rawPassword, encodedPassword);
}
}