30.管理员登录三部曲
管理员登录三部曲
需求分析:
管理员发起登录请求,登录成功后进入主页。
在前后端分离的项目中,一次登录往往会发送多次请求。
1.获取验证码图片
2.用户登录,获得token
3.根据token获取用户信息
实体类(对应数据库表结构)
package com.tanhua.model.domain;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
//后台系统的管理员对象
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Admin implements Serializable {
/**
* id
*/
private Long id;
/**
* 用户名
*/
private String username;
/**
* 密码
*/
private String password;
/**
* 头像
*/
private String avatar;
}
一、获取验证码图片
SystemController
/**
* 获取图片验证码:
* 请求路径:/system/users/verification
* 请求方式:get
* 请求参数:String uuid
* 响应数据:
* 实现思路: 1.调用CaptchaUtil获取验证码图片,里面包含验证码图片和验证码
* 2.把验证码存入redis
3.响应验证码图片
**/
@GetMapping("/verification")
public void verification(String uuid, HttpServletResponse response) throws IOException {
//1.调用CaptchaUtil获取验证码对象,里面包含验证码图片和验证码
CircleCaptcha circleCaptcha = CaptchaUtil.createCircleCaptcha(299, 97);
String code = circleCaptcha.getCode();//验证码
//2.把验证码存进redis
String key = Constants.CAPT_CODE +uuid;
redisTemplate.opsForValue().set(key, code);
//3.响应验证码图片
circleCaptcha.write(response.getOutputStream());
}
二、用户登录
SystemController
/**
* 用户登录
* 请求路径:/system/users/login
* 请求方式:post
* 请求参数:String username(账号),
* String password(密码),
* String verificationCode(验证码),
* String uuid
* 使用map集合接收参数
* 响应数据:
*/
@PostMapping("/login")
public ResponseEntity userLogin(@RequestBody Map map){
Map tokenMap = adminService.userLogin(map);
return ResponseEntity.ok(tokenMap);
}
AdminService
1.接收参数
2.校验验证码(验证码错误,抛出异常)
3.根据用户名查询用户
4.判断用户是否存在、密码是否正确
5.登录成功,颁发token
/**
* 用户登录
* @param map
* @return
*/
public Map userLogin(Map map) {
//1.接收参数
String username = (String) map.get("username");
String password = (String) map.get("password");
String verificationCode = (String) map.get("verificationCode");
String uuid = (String) map.get("uuid");
//2.校验验证码
String key = Constants.CAPT_CODE + uuid;
String redisCode = redisTemplate.opsForValue().get(key);
if(StringUtils.isEmpty(verificationCode) || !redisCode.equals(verificationCode)){
//验证码错误,抛出异常
throw new BusinessException("验证码错误");
}
redisTemplate.delete(key);//校验成功,删除redis中的验证码
//3.根据用户名查询用户
QueryWrapper<Admin> qw = new QueryWrapper<>();
qw.eq("username", username);
Admin admin = adminMapper.selectOne(qw);
//4.判断用户是否存在、密码是否正确
password = SecureUtil.md5(password);
if(admin == null || !admin.getPassword().equals(password)){
throw new BusinessException("用户名或者密码错误");
}
//5.登录成功,颁发token
Map tokenMap = new HashMap();
tokenMap.put("id", admin.getId());
tokenMap.put("username", admin.getUsername());
//该死的千万别用错对象了这次map.put("id", admin.getId());
//map.put("username", admin.getUsername());
String token = JwtUtils.getToken(tokenMap);
//6.返回token
Map returnMap = new HashMap();
returnMap.put("token",token);
return returnMap;
}
三、根据token获取用户信息
返回给页面的vo对象
package com.tanhua.model.vo;
import com.tanhua.model.domain.Admin;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class AdminVo {
/**
* id
*/
private String id;
/**
* 用户名
*/
private String username;
/**
* 头像
*/
private String avatar;
public static AdminVo init(Admin admin) {
AdminVo vo = new AdminVo();
vo.setAvatar(admin.getAvatar());
vo.setUsername(admin.getUsername());
vo.setId(admin.getId().toString());
return vo;
}
}
SystemController
/**
* 当前用户的基本信息
* 请求路径:/system/users/profile
* 请求方式:post
* 请求参数:
* 响应数据:AdminVo
*/
@PostMapping("/profile")
public ResponseEntity profile(){
AdminVo adminVo = adminService.profile();
return ResponseEntity.ok(adminVo);
}
AdminService
/**
* 获取当前登录用户信息
* @return
*/
public AdminVo profile() {
Long userId = AdminHolder.getUserId();
Admin admin = adminMapper.selectById(userId);
AdminVo adminVo = AdminVo.init(admin);
return adminVo;
}