diff --git a/pom.xml b/pom.xml index 8b12ac7..6ab3ae9 100644 --- a/pom.xml +++ b/pom.xml @@ -41,6 +41,11 @@ knife4j-openapi2-spring-boot-starter 4.4.0 + + + org.springframework.security + spring-security-crypto + com.mysql mysql-connector-j diff --git a/sql/create_table.sql b/sql/create_table.sql new file mode 100644 index 0000000..3718b59 --- /dev/null +++ b/sql/create_table.sql @@ -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; diff --git a/src/main/java/edu/whut/smilepicturebackend/SmilePictureBackendApplication.java b/src/main/java/edu/whut/smilepicturebackend/SmilePictureBackendApplication.java index a1a85ad..b510a0d 100644 --- a/src/main/java/edu/whut/smilepicturebackend/SmilePictureBackendApplication.java +++ b/src/main/java/edu/whut/smilepicturebackend/SmilePictureBackendApplication.java @@ -1,9 +1,11 @@ package edu.whut.smilepicturebackend; +import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication +@MapperScan("edu.whut.smilepicturebackend.mapper") public class SmilePictureBackendApplication { public static void main(String[] args) { diff --git a/src/main/java/edu/whut/smilepicturebackend/config/SecurityConfig.java b/src/main/java/edu/whut/smilepicturebackend/config/SecurityConfig.java new file mode 100644 index 0000000..f8d36da --- /dev/null +++ b/src/main/java/edu/whut/smilepicturebackend/config/SecurityConfig.java @@ -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 是强度 + } +} diff --git a/src/main/java/edu/whut/smilepicturebackend/controller/UserController.java b/src/main/java/edu/whut/smilepicturebackend/controller/UserController.java new file mode 100644 index 0000000..5fc3493 --- /dev/null +++ b/src/main/java/edu/whut/smilepicturebackend/controller/UserController.java @@ -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 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); + } +} diff --git a/src/main/java/edu/whut/smilepicturebackend/mapper/UserMapper.java b/src/main/java/edu/whut/smilepicturebackend/mapper/UserMapper.java new file mode 100644 index 0000000..9518645 --- /dev/null +++ b/src/main/java/edu/whut/smilepicturebackend/mapper/UserMapper.java @@ -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 { + +} + + + + diff --git a/src/main/java/edu/whut/smilepicturebackend/model/dto/UserRegisterRequest.java b/src/main/java/edu/whut/smilepicturebackend/model/dto/UserRegisterRequest.java new file mode 100644 index 0000000..342b386 --- /dev/null +++ b/src/main/java/edu/whut/smilepicturebackend/model/dto/UserRegisterRequest.java @@ -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; + +} diff --git a/src/main/java/edu/whut/smilepicturebackend/model/entity/User.java b/src/main/java/edu/whut/smilepicturebackend/model/entity/User.java new file mode 100644 index 0000000..be627ab --- /dev/null +++ b/src/main/java/edu/whut/smilepicturebackend/model/entity/User.java @@ -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; +} \ No newline at end of file diff --git a/src/main/java/edu/whut/smilepicturebackend/model/enums/UserRoleEnum.java b/src/main/java/edu/whut/smilepicturebackend/model/enums/UserRoleEnum.java new file mode 100644 index 0000000..20d1822 --- /dev/null +++ b/src/main/java/edu/whut/smilepicturebackend/model/enums/UserRoleEnum.java @@ -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; + } +} diff --git a/src/main/java/edu/whut/smilepicturebackend/service/UserService.java b/src/main/java/edu/whut/smilepicturebackend/service/UserService.java new file mode 100644 index 0000000..84adb1b --- /dev/null +++ b/src/main/java/edu/whut/smilepicturebackend/service/UserService.java @@ -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 { + /** + * 用户注册 + * + * @param userAccount 用户账户 + * @param userPassword 用户密码 + * @param checkPassword 校验密码 + * @return 新用户 id + */ + long userRegister(String userAccount, String userPassword, String checkPassword); + /** + * 获取加密后的密码 + * + * @param userPassword + * @return + */ + + + String getEncryptPassword(String userPassword); +} diff --git a/src/main/java/edu/whut/smilepicturebackend/service/impl/UserServiceImpl.java b/src/main/java/edu/whut/smilepicturebackend/service/impl/UserServiceImpl.java new file mode 100644 index 0000000..443b1ad --- /dev/null +++ b/src/main/java/edu/whut/smilepicturebackend/service/impl/UserServiceImpl.java @@ -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 + 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 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()); + } +} + + + + diff --git a/src/main/java/edu/whut/smilepicturebackend/utils/PasswordUtils.java b/src/main/java/edu/whut/smilepicturebackend/utils/PasswordUtils.java new file mode 100644 index 0000000..c34935c --- /dev/null +++ b/src/main/java/edu/whut/smilepicturebackend/utils/PasswordUtils.java @@ -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); + } +}