保姆级笔记:人脸识别智能管理系统--第二天
第二天笔记
本章内容:完善后端代码,将验证码存入redis,同时完成登录接口
2.1进行redis配置
打开后端项目的application.yml
添加redis相关配置,最终application.yml内容如下:
spring:
application:
name: cv
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/community?useUnicode=true&characterEncoding=utf-8
username: 'root'
password: '!Aa711217720414'
#新增代码
redis:
open: true
database: 2 # 2号数据库
host: localhost #redis地址
port: 6379 #redis端口
#
server:
port: 8083
2.2调用api操作redis
在LoginController.java中注入RedisTemplate:
@RestController
public class LoginController {
@Autowired
private RedisTemplate redisTemplate;//注入RedisTemplate
将生成的验证码存入redis:
直接运行项目后端,但后打开RedisDesktop查看数据:
向redis添加成功。
2.3完成登录逻辑
2.3.1找到前端逻辑
找到前端页面index.vue
找到登录按钮,找到相应的登录方法
跳转到方法相应的位置
然后跳转到store/modules/user.js里的login方法
发现里面调用了login()方法,因此再寻找根文件:
跳转到src/api/sys/user.js里的login方法
因此,后台登录接口的url为“/login”
2.3.2编写登录接口
登录接口使用post请求,因为是提交数据,且需要返回一个Token。
(即登录成功之后生成一个令牌,将令牌传到后端,该令牌就代表登录状态。因此每次操作时后端都需要去验证该令牌是否正确。若令牌正确,则可以进行操作。若令牌失效,则需要重新登录。)
接口文档:
根据API文档中的参数,建立form.LoginForm.java,表示输入的表单数据
LoginForm.java代码:
/**
* 功能:
* 作者:
* 日期:2024-07-16 11:55
*/
package com.cas.form;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class LoginForm {
//每一属性与api文档中的参数部分相对应
private String captcha;//登录表单中的验证码
private String password;//登录表单中的密码
private String username;//登录表单中的用户名
private String uuid;//登录表单中的uuid
}
在LoginController中编写登录接口
@PostMapping("/login")
public Result login(@RequestBody LoginForm loginForm, HttpSession session){//该方法接收登录表单对象LoginForm,等同于前端目录中src/views/login/index.vue中handleLogin里的LoginForm对象。注意,由于前端传递的是json数据,因此需要采用@RequestBody将json格式转换为java对象 //session表示当登录成功后,将当前用户存入session中。后端存入session,前端存入cookie
}
设计登录逻辑。由于登录时需要判断用户名、密码、验证码与用户状态,因此按顺序进行验证。在LoginController.java编写验证接口:
//登录接口
@PostMapping("/login")
public Result login(@RequestBody LoginForm loginForm, HttpSession session){//该方法接收登录表单对象LoginForm,等同于前端目录中src/views/login/index.vue中handleLogin里的LoginForm对象。注意,由于前端传递的是json数据,因此需要采用@RequestBody将json格式转换为java对象
//session表示当登录成功后,将当前用户存入session中。后端存入session,前端存入cookie
//第一步:验证码校验
//从Redis中获取验证码
String code = (String)this.redisTemplate.opsForValue().get(loginForm.getUuid());
//判断验证码是否有效
if(code==null){//验证码为空,表示验证码失效
return Result.ok().put("status","fail").put("data","验证码已过期");//ok()表示前后端已连通,code==null表示验证码失效
}
//判断验证码是否正确
if(!code.equals(loginForm.getCaptcha())){//若验证码不匹配
return Result.ok().put("status","fail").put("data","验证码错误");
}
//若验证码通过验证,则判断用户名是否正确,需要注入UserService
QueryWrapper<User> queryWrapper=new QueryWrapper<>();
queryWrapper.eq("username",loginForm.getUsername());//将数据库表中的username与输入的用户名进行比较
User user=this.userService.getOne(queryWrapper);
if(user==null){//如果没有输入用户名
return Result.ok().put("status","fail").put("data","用户名不存在");
}
//若用户名正确,则判断密码是否正确
String password= SecureUtil.sha256(loginForm.getPassword());//因为数据库的密码是经过加密之后的,所以输入密码之后也需要加密
if(!password.equals(user.getPassword())){//若不相等,则密码错误。注意,该password是从数据库里面查出来的,因此要通过user调用
return Result.ok().put("status","fail").put("data","密码错误");
}
//查看用户状态,是否被锁定
if(user.getStatus()==0){//此时用户被锁定
return Result.ok().put("status","fail").put("data","当前用户被锁定");
}
//若全部验证通过,则登录成功,将user存入session中
session.setAttribute("user",user);
return Result.ok().put("status","success");
}
登录成功以后,需要创建Token并对Token进行验证,因此在application.yml中添加如下配置,设置jwt的相关参数:
jwt:
secret: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4K67DMlSPXbgG0MPp0gH # jwt密钥
expire: 86400000 # jwt生存时间
# expire: 10000
subject: door # jwt标题
在utils文件夹中导入JwtUtil.java
JwtUtil.java代码:
package com.cas.utils;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import java.util.Date;
import java.util.UUID;
@ConfigurationProperties(prefix = "jwt") //在配置文件中找到前缀为"jwt”的属性
@Component
public class JwtUtil {
private long expire;
private String secret;
private String subject;
/**
* 生成token
*
* @param userId
* @return
*/
public String createToken(String userId) {
String token = Jwts.builder()
//载荷:自定义信息
.claim("userId", userId)
//载荷:默认信息
.setSubject(subject) //令牌主题
.setExpiration(new Date(System.currentTimeMillis() + expire)) //过期时间
.setId(UUID.randomUUID().toString())
//签名哈希
.signWith(SignatureAlgorithm.HS256, secret)
//组装jwt字符串
.compact();
return token;
}
public boolean checkToken(String token){
if(StringUtils.isEmpty(token)){
return false;
}
try {
Jws<Claims> claimsJws = Jwts.parser().setSigningKey(secret).parseClaimsJws(token);
} catch (Exception e) {
return false;
}
return true;
}
public long getExpire() {
return expire;
}
public void setExpire(long expire) {
this.expire = expire;
}
public String getSecret() {
return secret;
}
public void setSecret(String secret) {
this.secret = secret;
}
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
}
然后在LoginController.java中添加jwt验证过程,首先注入JwtUtil:
然后在LoginController.java的登录接口中追加token建立与验证过程。完整的登录接口如下:
//登录接口
@PostMapping("/login")
public Result login(@RequestBody LoginForm loginForm, HttpSession session){//该方法接收登录表单对象LoginForm,等同于前端目录中src/views/login/index.vue中handleLogin里的LoginForm对象。注意,由于前端传递的是json数据,因此需要采用@RequestBody将json格式转换为java对象
//session表示当登录成功后,将当前用户存入session中。后端存入session,前端存入cookie
//第一步:验证码校验
//从Redis中获取验证码
String code = (String)this.redisTemplate.opsForValue().get(loginForm.getUuid());
//判断验证码是否有效
if(code==null){//验证码为空,表示验证码失效
return Result.ok().put("status","fail").put("data","验证码已过期");//ok()表示前后端已连通,code==null表示验证码失效
}
//判断验证码是否正确
if(!code.equals(loginForm.getCaptcha())){//若验证码不匹配
return Result.ok().put("status","fail").put("data","验证码错误");
}
//若验证码通过验证,则判断用户名是否正确,需要注入UserService
QueryWrapper<User> queryWrapper=new QueryWrapper<>();
queryWrapper.eq("username",loginForm.getUsername());//将数据库表中的username与输入的用户名进行比较
User user=this.userService.getOne(queryWrapper);
if(user==null){//如果没有输入用户名
return Result.ok().put("status","fail").put("data","用户名不存在");
}
//若用户名正确,则判断密码是否正确
String password= SecureUtil.sha256(loginForm.getPassword());//因为数据库的密码是经过加密之后的,所以输入密码之后也需要加密
if(!password.equals(user.getPassword())){//若不相等,则密码错误。注意,该password是从数据库里面查出来的,因此要通过user调用
return Result.ok().put("status","fail").put("data","密码错误");
}
//查看用户状态,是否被锁定
if(user.getStatus()==0){//此时用户被锁定
return Result.ok().put("status","fail").put("data","当前用户被锁定");
}
//若全部验证通过,则登录成功,将user存入session中
session.setAttribute("user",user);
//登录成功以后,需要创建token,使用工具类jwt
String token=this.jwtUtil.createToken(String.valueOf(user.getUserId()));
//将创建好的token存入redis
redisTemplate.opsForValue().set("user-"+user.getUserId(),token,jwtUtil.getExpire());
//将token与有效期进行返回
Map<String,Object> map=new HashMap<>();
map.put("token",token);//token值
map.put("expire",jwtUtil.getExpire());//有效日期
return Result.ok().put("status","success").put("data",map);
}