============= 后端_用户登录 ============= 用户登录: - 验证账号密码 - 为用户生成令牌 - 将令牌和用户的信息保存在Redis中 - 将令牌返回前端 1 添加依赖 /ysdblog-api/pom.xml: commons-codec commons-codec 2 配置Redis /ysdblog-api/src/main/resources/application.properties: ... # Redis spring.redis.host=localhost spring.redis.port=6379 ... 3 错误码枚举 /ysdblog-api/src/main/java/com/weihome/ysdblog/vo/ErrorCode.java: public enum ErrorCode { PARAM_ERROR(10001, "参数有误"), ACCOUNT_PWD_NOT_EXIST(10002, "用户名或密码不存在"), TOKEN_ERROR(10003, "令牌有误"), ACCOUNT_EXIST(10004, "账号已存在"), UPLOAD_ERROR(20001, "上传失败"), NO_PERMISSION(70001, "无访问权限"), SESSION_TIME_OUT(90001, "会话超时"), NO_LOGIN(90002, "未登录"),; private Integer code; private String msg; ErrorCode(Integer code, String msg){ this.code = code; this.msg = msg; } public Integer getCode() { return code; } public void setCode(Integer code) { this.code = code; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } } 4 视图对象 4.1 登录参数视图对象 /ysdblog-api/src/main/java/com/weihome/ysdblog/vo/params/LoginParam.java: @Data public class LoginParam { private String account; private String password; } 5 用户服务 5.1 用户服务接口 /ysdblog-api/src/main/java/com/weihome/ysdblog/service/UserService.java: public interface UserService { ... /** * 根据账号密码查询用户 */ public User findUser(String account, String password); ... } 5.2 用户服务实现 /ysdblog-api/src/main/java/com/weihome/ysdblog/service/impl/UserServiceImpl.java: ... public class UserServiceImpl implements UserService { ... @Override public User findUser(String account, String password) { LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.eq(User::getAccount, account); queryWrapper.eq(User::getPassword, password); queryWrapper.select(User::getId, User::getAccount, User::getAvatar, User::getNickname); queryWrapper.last("limit 1"); return userMapper.selectOne(queryWrapper); } ... } 6 登录服务 6.1 登录服务接口 /ysdblog-api/src/main/java/com/weihome/ysdblog/service/LoginService.java: public interface LoginService { /** * 用户登录 */ public Result login(LoginParam loginParam); } 6.2 登录服务实现 /ysdblog-api/src/main/java/com/weihome/ysdblog/service/impl/LoginServiceImpl.java: @Service public class LoginServiceImpl implements LoginService { @Autowired private UserService userService; @Autowired private RedisTemplate redisTemplate; @Override public Result login(LoginParam loginParam) { String account = loginParam.getAccount(); String password = loginParam.getPassword(); // 检查账号密码是否合法 if (StringUtils.isBlank(account) || StringUtils.isBlank(password)) return Result.fail( ErrorCode.PARAM_ERROR.getCode(), ErrorCode.PARAM_ERROR.getMsg()); // 检查账号密码是否存在 User user = userService.findUser(account, DigestUtils.md5Hex(password + salt)); if (user == null) return Result.fail( ErrorCode.ACCOUNT_PWD_NOT_EXIST.getCode(), ErrorCode.ACCOUNT_PWD_NOT_EXIST.getMsg()); // 为该用户生成令牌 String token = JWTUtils.createToken(user.getId()); // 将令牌和用户的对应关系保存到Redis中并将过期时间设置为1天 redisTemplate.opsForValue().set("TOKEN_" + token, JSON.toJSONString(user), 1, TimeUnit.DAYS); // 返回令牌给前端 return Result.success(token); } public static void main(String[] args) { System.out.println( DigestUtils.md5Hex("123456" + salt)); } } 7 登录控制器 /ysdblog-api/src/main/java/com/weihome/ysdblog/controller/LoginController.java: @RestController @RequestMapping("login") public class LoginController { @Autowired private LoginService loginService; /** * 用户登录 */ @PostMapping public Result login(@RequestBody LoginParam loginParam) { return loginService.login(loginParam); } } 8 运行测试 Postman POST localhost:8888/login Body { "account": "user_a", "password": "123456" } ---------------------------- { "success": true, "code": 200, "msg": "success", "data": "eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE2NDk1NzgzNjUsInVzZXJJZCI6MSwiaWF0IjoxNjQ4Njg5MzMyfQ.GSsoLNluJwDseqaglBBvKmMZdtdBapInPdnTHs3oXv8" } 检查Redis库,新增如下键值对: 键:TOKEN_eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE2NDk1NzgzNjUsInVzZXJJZCI6MSwiaWF0IjoxNjQ4Njg5MzMyfQ.GSsoLNluJwDseqaglBBvKmMZdtdBapInPdnTHs3oXv8 值:{"account":"user_a","avatar":"user_a.png","id":1,"nickname":"nickname_a"}