首先我们来认识一下Jwt令牌是什么https://zhuanlan.zhihu.com/p/370670759
Jwt在后端的使用:
Jwt工具类:
首先我们有一个工具类,用于解析和生成前端传过来的登录信息:
package com.wjf666.utils;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.util.Date;
import java.util.Map;
public class JwtUtils {
private static String signKey = "wjf666";
private static Long expire = 43200000L;
/**
* 生成JWT令牌
* @param claims JWT第二部分负载 payload 中存储的内容
* @return
*/
public static String generateJwt(Map<String, Object> claims){
String jwt = Jwts.builder()
.addClaims(claims)
.signWith(SignatureAlgorithm.HS256, signKey)
.setExpiration(new Date(System.currentTimeMillis() + expire))
.compact();
return jwt;
}
/**
* 解析JWT令牌
* @param jwt JWT令牌
* @return JWT第二部分负载 payload 中存储的内容
*/
public static Claims parseJWT(String jwt){
Claims claims = Jwts.parser()
.setSigningKey(signKey)
.parseClaimsJws(jwt)
.getBody();
return claims;
}
}
这边的signKey是你的签名,用于解析Jwt,这边的expire是签名的有效时间,后面可以通过判断有效时间来对用户的操作进行限制。
generateJwt函数主要是用于传入一个map,其中存储用户的信息,然后把这些信息加入Jwt存储
parseJwt函数主要是传入一个Jwt字符串,然后传出一个Claim,这个类继承了map类,可以用于获取解析后的Jwt里面的信息。
用户登录接口:
@PostMapping("/login")
public Result login(@RequestBody Emp emp) {
Emp e = empService.login(emp);
// 登录成功,下放令牌
if (e != null) {
Map<String, Object> claims = new HashMap<>();
claims.put("username", e.getUsername());
claims.put("password", e.getPassword());
String Jwt = JwtUtils.generateJwt(claims); //Jwt包含当前登录员工信息
return Result.success(Jwt);
} else {
return Result.error("用户名或密码错误");
}
}
这里返回了一个字符串Jwt,然后前端进行存储。
每次请求验证接口:
@PostMapping("/verify")
public Result verify(HttpServletRequest request) {
String token = request.getHeader("token");
try {
JwtUtils.parseJWT(token);
return Result.success(token);
} catch (Exception e) {
return Result.success();
}
}
每次前端请求头携带token信息,然后后端获取token信息并对其进行解析,解析失败就返回null,解析成功返回token。
Jwt在前端的使用:
Jwt的存储:
login() {
axios.post('/api/login/', this.emp).then(resp => {
if (resp.data.msg === 'success') {
this.$message({
message: "登陆成功",
type: 'success'
});
setTimeout(() => {
localStorage.setItem("token",JSON.stringify(resp.data.data));
this.$router.push('/home'); // 跳转到登录页面
}, 2000); // 延时 2 秒跳转
} else {
this.$message({
message: resp.data.msg,
type: 'error'
});
}
}
).catch(e => {
console.log(e)
})
}
登录成功用localStorage进行存储
Jwt的验证:
首先在data的部分定义token,获取本地存储的token:
token: JSON.parse(localStorage.getItem("token"))
然后在钩子函数中进行验证:
mounted() {
axios.post("/api/verify/", null, {
headers:
{
token: this.token
}
}).then(resp => {
console.log(resp.data);
if(resp.data.data == null)
{
this.$router.push('/login');
this.$message.error('身份过期,请重新登录');
}
})
this.loadDepts();
}
可以结合上面的验证接口,如果返回null就是Jwt有问题就返回到登录界面重新登录,这边Jwt问题不一定是令牌过期,可以结合实际情况编程,这边图方便就直接使用令牌过期来了。
这边也是为了图方便,在每次路由切换页面的时候才判断令牌是否有效,其实是可以在每次对后端接口进行请求的时候都判断一次,这样就需要使用到过滤器Filter。