基于uniapp原生组件uni-ui 做一个登录注册与个人中心(后端篇)

以你之姓@ 2024-03-16 07:26 71阅读 0赞

基于uniapp原生组件uni-ui 做一个登录注册与个人中心(后端篇)

简介

本文使用springboot+mybatis-plus实现用户表的后端代码,包含加密功能。

数据库

  1. CREATE TABLE `user` (
  2. `id` int NOT NULL AUTO_INCREMENT,
  3. `username` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
  4. `avatar` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
  5. `password_hash` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
  6. `salt` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
  7. `grade` int NOT NULL,
  8. `role` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
  9. PRIMARY KEY (`id`) USING BTREE
  10. ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin ROW_FORMAT = DYNAMIC;

在这里插入图片描述

项目编写

  • 创建项目
    在这里插入图片描述

在这里插入图片描述

  • pom.xml

    <?xml version=”1.0” encoding=”UTF-8”?>
    <project xmlns=”http://maven.apache.org/POM/4.0.0“ xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance“

    1. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    2. <modelVersion>4.0.0</modelVersion>
    3. <parent>
    4. <groupId>org.springframework.boot</groupId>
    5. <artifactId>spring-boot-starter-parent</artifactId>
    6. <version>2.7.11</version>
    7. <relativePath/> <!-- lookup parent from repository -->
    8. </parent>
    9. <groupId>com.example</groupId>
    10. <artifactId>UserDemo</artifactId>
    11. <version>0.0.1-SNAPSHOT</version>
    12. <name>UserDemo</name>
    13. <description>UserDemo</description>
    14. <properties>
    15. <java.version>17</java.version>
    16. </properties>
    17. <dependencies>
    18. <dependency>
    19. <groupId>org.springframework.boot</groupId>
    20. <artifactId>spring-boot-starter-web</artifactId>
    21. <version>2.7.6</version>
    22. </dependency>
    23. <dependency>
    24. <groupId>org.springframework.data</groupId>
    25. <artifactId>spring-data-jpa</artifactId>
    26. <version>2.5.6</version>
    27. </dependency>
    28. <dependency>
    29. <groupId>org.hibernate</groupId>
    30. <artifactId>hibernate-core</artifactId>
    31. <version>5.6.3.Final</version>
    32. </dependency>
  1. <dependency>
  2. <groupId>javax.persistence</groupId>
  3. <artifactId>javax.persistence-api</artifactId>
  4. <version>2.2</version>
  5. </dependency>
  6. <dependency>
  7. <groupId>org.mybatis.spring.boot</groupId>
  8. <artifactId>mybatis-spring-boot-starter</artifactId>
  9. <version>2.3.0</version>
  10. </dependency>
  11. <dependency>
  12. <groupId>org.mybatis.spring.boot</groupId>
  13. <artifactId>mybatis-spring-boot-starter</artifactId>
  14. <version>2.3.0</version>
  15. </dependency>
  16. <dependency>
  17. <groupId>com.mysql</groupId>
  18. <artifactId>mysql-connector-j</artifactId>
  19. <scope>runtime</scope>
  20. </dependency>
  21. <dependency>
  22. <groupId>org.projectlombok</groupId>
  23. <artifactId>lombok</artifactId>
  24. <optional>true</optional>
  25. </dependency>
  26. <dependency>
  27. <groupId>org.springframework.boot</groupId>
  28. <artifactId>spring-boot-starter-test</artifactId>
  29. <scope>test</scope>
  30. </dependency>
  31. <dependency>
  32. <groupId>com.baomidou</groupId>
  33. <artifactId>mybatis-plus-boot-starter</artifactId>
  34. <version>3.4.2</version>
  35. </dependency>
  36. <dependency>
  37. <groupId>io.jsonwebtoken</groupId>
  38. <artifactId>jjwt-api</artifactId>
  39. <version>0.11.2</version>
  40. </dependency>
  41. <!-- 如果要使用 jjwt 的实现,还需要添加以下依赖 -->
  42. <dependency>
  43. <groupId>io.jsonwebtoken</groupId>
  44. <artifactId>jjwt-impl</artifactId>
  45. <version>0.11.2</version>
  46. <scope>runtime</scope>
  47. </dependency>
  48. <dependency>
  49. <groupId>io.jsonwebtoken</groupId>
  50. <artifactId>jjwt-jackson</artifactId>
  51. <version>0.11.2</version>
  52. <scope>runtime</scope>
  53. </dependency>
  54. <!-- Hibernate Validator -->
  55. <dependency>
  56. <groupId>org.springframework.boot</groupId>
  57. <artifactId>spring-boot-starter-validation</artifactId>
  58. </dependency>
  59. <dependency>
  60. <groupId>org.apache.shiro</groupId>
  61. <artifactId>shiro-core</artifactId>
  62. <version>1.8.0</version>
  63. </dependency>
  64. <dependency>
  65. <groupId>org.apache.commons</groupId>
  66. <artifactId>commons-lang3</artifactId>
  67. <version>3.12.0</version>
  68. </dependency>
  69. </dependencies>
  70. <build>
  71. <plugins>
  72. <plugin>
  73. <groupId>org.springframework.boot</groupId>
  74. <artifactId>spring-boot-maven-plugin</artifactId>
  75. <configuration>
  76. <excludes>
  77. <exclude>
  78. <groupId>org.projectlombok</groupId>
  79. <artifactId>lombok</artifactId>
  80. </exclude>
  81. </excludes>
  82. </configuration>
  83. </plugin>
  84. </plugins>
  85. </build>
  86. </project>
  • application.properties

    ?????

    spring.datasource.url=jdbc:mysql://localhost:3306/exam4?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
    spring.datasource.username=root
    spring.datasource.password=123456
    spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

    ???????

    server.port=8081

    MyBatis-Plus ??

    mybatis-plus.mapper-locations=classpath:/mapper/*.xml
    mybatis-plus.type-aliases-package=com.example.demo.entity
    mybatis-plus.global-config.db-config.id-type=auto
    mybatis-plus.configuration.map-underscore-to-camel-case=true
    mybatis-plus.configuration.use-generated-keys=true
    mybatis-plus.configuration.map-enum-as-ordinal=false
    mybatis-plus.configuration.enum-handler=com.baomidou.mybatisplus.extension.handlers.MybatisEnumTypeHandler

代码编写

项目结构
在这里插入图片描述

Bean

User

  1. import lombok.AllArgsConstructor;
  2. import lombok.Data;
  3. import com.baomidou.mybatisplus.annotation.*;
  4. import lombok.NoArgsConstructor;
  5. @Data
  6. @AllArgsConstructor
  7. @NoArgsConstructor
  8. @TableName("user")
  9. public class User {
  10. @TableId(type = IdType.AUTO)
  11. private Long id;
  12. private String username;
  13. private String avatar;
  14. private String passwordHash;
  15. private String salt;
  16. private int grade;
  17. private String role;
  18. }

Result

  1. import lombok.Data;
  2. import org.springframework.lang.Nullable;
  3. @Data
  4. public class Result<T> {
  5. private int code;
  6. private String message;
  7. @Nullable
  8. private T data;
  9. public static <T> Result<T> success(T data) {
  10. return success(data, "操作成功");
  11. }
  12. public static <T> Result<T> success(T data, String message) {
  13. return new Result<>(200, message, data);
  14. }
  15. public static <T> Result<T> fail(String message) {
  16. return new Result<>(500, message, null);
  17. }
  18. public Result(int code, String message, @Nullable T data) {
  19. this.code = code;
  20. this.message = message;
  21. this.data = data;
  22. }
  23. }

Tool

  1. import java.security.MessageDigest;
  2. import java.security.NoSuchAlgorithmException;
  3. /**
  4. * 安全相关工具类
  5. * 提供各种安全相关的操作方法
  6. */
  7. public class SecurityTool {
  8. /**
  9. * 对字符串进行MD5加密
  10. * @param str 待加密的字符串
  11. * @return 加密结果
  12. */
  13. public static String MD5Encode(String str) {
  14. try {
  15. MessageDigest md = MessageDigest.getInstance("MD5");
  16. md.update(str.getBytes()); //对字符串加密
  17. byte[] encodedBytes = md.digest();
  18. StringBuffer hexString = new StringBuffer();
  19. for (int i = 0; i < encodedBytes.length; i++) {
  20. String hex = Integer.toHexString(0xff & encodedBytes[i]);
  21. if (hex.length() == 1) {
  22. hexString.append('0');
  23. }
  24. hexString.append(hex);
  25. }
  26. return hexString.toString();
  27. } catch (NoSuchAlgorithmException e) {
  28. //省略异常处理
  29. }
  30. return null;
  31. }
  32. }

Config

CorsConfig
  1. import org.springframework.context.annotation.Bean;
  2. import org.springframework.context.annotation.Configuration;
  3. import org.springframework.web.servlet.config.annotation.CorsRegistry;
  4. import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
  5. import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
  6. @Configuration
  7. public class CorsConfig {
  8. @Bean
  9. public WebMvcConfigurer corsConfigurer() {
  10. return new WebMvcConfigurerAdapter() {
  11. @Override
  12. public void addCorsMappings(CorsRegistry registry) {
  13. // 允许来自本地的8080端口发起的跨域请求
  14. registry.addMapping("/api/**")
  15. .allowedOrigins("*")
  16. .allowedMethods("GET", "POST", "PUT", "DELETE")
  17. .allowCredentials(true).maxAge(3600);
  18. }
  19. };
  20. }
  21. }

Mapper

UserMapper
  1. import com.baomidou.mybatisplus.core.mapper.BaseMapper;
  2. import com.example.userdemo.Bean.User;
  3. import org.apache.ibatis.annotations.Mapper;
  4. @Mapper
  5. public interface UserMapper extends BaseMapper<User> {
  6. }

Service

IUserService
  1. import com.baomidou.mybatisplus.extension.service.IService;
  2. import com.example.userdemo.Bean.User;
  3. public interface IUserService extends IService<User> {
  4. /**
  5. * 用户注册
  6. * @param user 待注册用户信息
  7. * @return 注册成功返回true,失败返回false
  8. */
  9. boolean register(User user);
  10. /**
  11. * 用户登录
  12. * @param username 用户名
  13. * @param password 密码
  14. * @return 登录成功返回对应用户的信息,失败返回null
  15. */
  16. User login(String username, String password);
  17. /**
  18. * 根据用户名获取用户
  19. * @param username 用户名
  20. * @return 用户
  21. */
  22. User getByUsername(String username);
  23. }

Impl

UserServiceImpl
  1. import java.util.ArrayList;
  2. import java.util.Random;
  3. @Service
  4. public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
  5. /**
  6. * 用户注册实现
  7. * 先查用户名是否存在,不存在则加密密码进行保存
  8. * @param user 待注册用户信息
  9. * @return 注册成功返回true,失败返回false
  10. */
  11. @Override
  12. public boolean register(User user) {
  13. String username = user.getUsername();
  14. QueryWrapper<User> wrapper = new QueryWrapper<>();
  15. wrapper.eq("username", username); //查询用户名是否存在
  16. User hasUser = getOne(wrapper);
  17. if (hasUser != null) {
  18. //数据库中已经存在该用户名,注册失败
  19. return false;
  20. }
  21. // 随机生成一个头像
  22. ArrayList<String> arrayList = new ArrayList<>();
  23. arrayList.add("https://pic3.zhimg.com/v2-d6ddf0128212235dddf76df7f4383f53.jpg");
  24. arrayList.add("https://p0.ssl.img.360kuai.com/t01948ff2341a5d1ac3.jpg");
  25. arrayList.add("https://pic3.zhimg.com/v2-65020b1231ba55d55ee3d6a29ff3df26_r.jpg");
  26. arrayList.add("https://pic2.zhimg.com/v2-fc348d5e926116782149d2151dc09834.jpg");
  27. arrayList.add("https://pic4.zhimg.com/v2-797973e16edcd0ccaab44cfbfa08d2d3_r.jpg");
  28. Random random = new Random();
  29. user.setAvatar(arrayList.get(random.nextInt(arrayList.size())));
  30. String password = user.getPasswordHash();
  31. String salt = RandomStringUtils.randomAlphabetic(6); //生成盐
  32. String encryptedPwd = SecurityTool.MD5Encode(password + salt); //对密码+盐进行加密
  33. user.setPasswordHash(encryptedPwd);
  34. user.setSalt(salt);
  35. boolean successFlag = save(user);
  36. return successFlag;
  37. }
  38. @Override
  39. public User getByUsername(String username) {
  40. QueryWrapper<User> queryWrapper = new QueryWrapper<>();
  41. queryWrapper.eq("username", username);
  42. return getOne(queryWrapper);
  43. }
  44. /**
  45. * 用户登录实现
  46. * 先使用用户名查询对应用户,然后进行密码比对
  47. * @param username 用户名
  48. * @param password 密码
  49. * @return 如果成功则返回对应用户信息(不包含密码和盐),失败返回null
  50. */
  51. @Override
  52. public User login(String username, String password) {
  53. QueryWrapper<User> wrapper = new QueryWrapper<>();
  54. wrapper.eq("username", username); //根据用户名找到对应的User对象
  55. User user = getOne(wrapper);
  56. if (user == null) {
  57. //未找到该用户
  58. return null;
  59. }
  60. String salt = user.getSalt();
  61. String encryptedPwd = SecurityTool.MD5Encode(password + salt); //对密码+盐进行加密
  62. if (!encryptedPwd.equals(user.getPasswordHash())) {
  63. //密码错误
  64. return null;
  65. }
  66. user.setPasswordHash(null); //不暴露密码hash与盐值Salt给前端
  67. user.setSalt(null);
  68. return user; //一切正常,返回相应用户信息
  69. }
  70. }

Controller

UserController
  1. import com.baomidou.mybatisplus.core.toolkit.StringUtils;
  2. import com.example.userdemo.Bean.Result;
  3. import com.example.userdemo.Bean.User;
  4. import com.example.userdemo.Service.IUserService;
  5. import org.springframework.beans.factory.annotation.Autowired;
  6. import org.springframework.web.bind.annotation.*;
  7. import java.util.ArrayList;
  8. import java.util.List;
  9. import java.util.Random;
  10. @RestController
  11. @RequestMapping("/user")
  12. public class UserController {
  13. @Autowired
  14. private IUserService userService;
  15. /**
  16. * 获取全部用户信息列表
  17. */
  18. @GetMapping("/all")
  19. public Result<List<User>> listAllUsers() {
  20. List<User> userList = userService.list();
  21. return Result.success(userList);
  22. }
  23. /**
  24. * 根据用户ID获取用户信息
  25. */
  26. @GetMapping("/{id}")
  27. public Result<User> getUserById(@PathVariable(value = "id") Long id) {
  28. User user = userService.getById(id);
  29. if (user == null) {
  30. return Result.fail("该用户不存在");
  31. }
  32. return Result.success(user);
  33. }
  34. /**
  35. * 更新用户信息
  36. */
  37. @PostMapping("/save")
  38. public Result<Boolean> UpdateUser(@RequestBody User user) {
  39. // 判断新的username是否合法
  40. if (StringUtils.isBlank(user.getUsername())) {
  41. return Result.fail("更新失败:用户名不能为空");
  42. }
  43. // 校验用户名是否重复,如果已经存在就返回错误信息
  44. User existingUser = userService.getByUsername(user.getUsername());
  45. if (existingUser != null && !existingUser.getId().equals(user.getId())) {
  46. return Result.fail("更新失败:该用户名已被占用");
  47. }
  48. // 获取旧用户并更新部分信息
  49. User oldUser = userService.getById(user.getId());
  50. if (oldUser == null) {
  51. return Result.fail("更新失败:该用户不存在");
  52. }
  53. oldUser.setUsername(user.getUsername());
  54. oldUser.setGrade(user.getGrade());
  55. oldUser.setPasswordHash(user.getPasswordHash());
  56. boolean flag = userService.save(oldUser);
  57. if (flag) {
  58. return Result.success(true, "保存成功");
  59. } else {
  60. return Result.fail("保存失败");
  61. }
  62. }
  63. /**
  64. * 根据用户ID删除用户信息
  65. */
  66. @DeleteMapping("/delete/{id}")
  67. public Result<Boolean> deleteUserById(@PathVariable(value = "id") Long id) {
  68. boolean flag = userService.removeById(id);
  69. if (flag) {
  70. return Result.success(true, "删除成功");
  71. } else {
  72. return Result.fail("删除失败");
  73. }
  74. }
  75. /**
  76. * 用户注册
  77. */
  78. @PostMapping("/register")
  79. public Result<Boolean> register(@RequestBody User user) {
  80. System.out.println(user);
  81. boolean flag = userService.register(user);
  82. if (flag) {
  83. return Result.success(true, "注册成功");
  84. } else {
  85. return Result.fail("注册失败,用户名已被占用");
  86. }
  87. }
  88. /**
  89. * 用户登录
  90. */
  91. @PostMapping("/login")
  92. public Result<User> login(@RequestBody User user) {
  93. String username = user.getUsername();
  94. String password = user.getPasswordHash();
  95. User user2 = userService.login(username, password);
  96. if (user == null) {
  97. return Result.fail("用户名或密码错误,登录失败");
  98. } else {
  99. return Result.success(user2, "登录成功");
  100. }
  101. }
  102. }

Postman测试

好的,请按照以下步骤在 Postman 中测试接口:

  1. 以 POST 请求方式发送以下数据至 http://localhost:8081/user/register

    {

    1. "username": "test123",
    2. "passwordHash": "test1234",
    3. "grade": 1

    }

若注册成功,会返回请求成功信息:

  1. {
  2. "code": 200,
  3. "message": "注册成功",
  4. "data": true
  5. }

若注册失败(用户名已存在),会返回出错信息:

  1. {
  2. "code": 500,
  3. "message": "注册失败,用户名已被占用",
  4. "data": null
  5. }
  1. 以 POST 请求方式发送以下数据至 http://localhost:8080/user/login

    {

    1. "username": "test123",
    2. "password": "test1234"

    }

若登录成功,会返回用户信息:

  1. {
  2. "code": 200,
  3. "message": "登录成功",
  4. "data": {
  5. "id": 用户ID,
  6. "username": "test123",
  7. "avatar": null,
  8. "passwordHash": null,
  9. "salt": null,
  10. "grade": 1,
  11. "role": null
  12. }
  13. }

若登录失败(用户名或密码错误),会返回出错信息:

  1. {
  2. "code": 500,
  3. "message": "用户名或密码错误,登录失败",
  4. "data": null
  5. }
  1. 以 GET 请求方式发送以下数据至 http://localhost:8080/user/all

若查询全部用户信息列表成功,会返回用户信息列表:

  1. {
  2. "code": 200,
  3. "message": "操作成功",
  4. "data": [
  5. {
  6. "id": 用户1ID,
  7. "username": "test123",
  8. "avatar": null,
  9. "passwordHash": null,
  10. "salt": null,
  11. "grade": 0,
  12. "role": null
  13. },
  14. {
  15. "id": 用户2ID,
  16. "username": "user",
  17. "avatar": null,
  18. "passwordHash": null,
  19. "salt": null,
  20. "grade": 1,
  21. "role": null
  22. }
  23. ]
  24. }
  1. 以 GET 请求方式发送以下数据至 http://localhost:8080/user/1 (用户ID为 1 的具体用户):

若根据 ID 获取用户信息成功,会返回对应的用户信息:

  1. {
  2. "code": 200,
  3. "message": "操作成功",
  4. "data": {
  5. "id": 用户1ID,
  6. "username": "test123",
  7. "avatar": null,
  8. "passwordHash": null,
  9. "salt": null,
  10. "grade": 0,
  11. "role": null
  12. }
  13. }

若未找到该用户,会返回出错信息:

  1. {
  2. "code": 500,
  3. "message": "该用户不存在",
  4. "data": null
  5. }
  1. 以 POST 请求方式发送以下数据至 http://localhost:8080/user/save

    {

    1. "id": <当前用户ID>,
    2. "username": "test321",
    3. "passwordHash": "test4321",
    4. "grade": 2

    }

若新增或更新成功,会返回请求成功信息:

  1. {
  2. "code": 200,
  3. "message": "保存成功",
  4. "data": true
  5. }

注意:若采用 POST 请求方式,请在请求头中添加 Content-Type 为 application/json。

希望这个例子可以帮助您更好地理解如何使用 Spring Boot 框架和 Postman 工具进行接口测试。

发表评论

表情:
评论列表 (有 0 条评论,71人围观)

还没有评论,来说两句吧...

相关阅读

    相关 django一个注册登录界面

    一、基于sb-admin模板完成以下登录的逻辑 用户想要访问一个网页,首先要求注册账号,有了账号之后再去登录,才能访问网站的主页 1.先说以下用户注册的逻辑: r