=============
后端_用户登录
=============
用户登录:
- 验证账号密码
- 为用户生成令牌
- 将令牌和用户的信息保存在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"}