Token令牌
关系型数据库(mysql)数据保存在磁盘文件,使用I/O流读取数据
redis(内/缓存数据库)数据保存在内存中
前后端分离时,html没有session保存用户信息,服务器端如何判断当前是哪个用户发起的请求?
令牌机制:由服务器发行,客户端佩戴
客户端每一次发送请求都会在请求头中携带令牌,
服务器端验证token是否有效
配置跨域:
WebFilter(filterName = "ConfigFilter",urlPatterns = "/*")
public class ConfigFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletResponse resp=(HttpServletResponse) servletResponse;
//跨域请求头
resp.setHeader("Access-Control-Allow-Headers", "*");
//允许所有的方法访问 如post , get,delete,put,options方法
resp.setHeader("Access-Control-Allow-Method", "*");
//缓存时间
resp.setHeader("Access-Control-Hax-Age", "3600");
//允许跨域主机地址
resp.setHeader("Access-Control-Allow-Origin","*");
//是否携带cookie
resp.setHeader("Access-Control-Allow-Credentials","ture");
request.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=UTF-8");
//放行
filterChain.doFilter(request, resp);
}
@Override
public void destroy() {
}
}
util包创建tonken类:
package utils;
import lombok.Data;
import java.io.Serializable;
@Data
public class Token<T> implements Serializable {
private String code=null;
private String message=null;//信息提示
private String token=null;//保存token信息
private T t;
}
创建Token:
传入的agent是从前端获取
//req是request的简写
String agent=req.getHeader("User-Agent");
public String createTiken(String agent){
//agent用于获取设备信息:pc端,移动端
UserAgent userAgent=UserAgent.parseUserAgentString(agent);
OperatingSystem operatingSystem=userAgent.getOperatingSystem();
DeviceType deviceType=operatingSystem.getDeviceType();
String token=null;
if (deviceType.equals(DeviceType.COMPUTER)){
token="pc";
}if (deviceType.equals(DeviceType.UNKNOWN)){
token="unkonw";
}if (deviceType.equals(DeviceType.MOBILE)){
token="mobile";
}if (deviceType.equals(DeviceType.TABLET)){
token="pc";
}
//创建token唯一
String uuid=token+"_"+System.currentTimeMillis()+"_"+UUID.randomUUID().toString();
return uuid;
}
redis保存token令牌(创建的token为key,用户信息为value)
public void save(String token, User user) {
System.out.println("连接redis");
//创建redis连接,localhost是主机地址
Jedis jedis=new Jedis("localhost");
//auth 输入密码
jedis.auth("123456");
//清空当前数据库
jedis.flushDB();
//保存token
jedis.set(token, JSON.toJSONString(user));//token做key,user做value,保存用户信息
//判断设备是移动端还是企业端
String deviceType =token.split("_")[0];
System.out.println(deviceType);
if (deviceType.equals("pc")){
//如果是移动端,设置token时长为2小时
jedis.expire(token,3600*2);
}
}
service层返回token令牌:
public Token<User> doLogin(String username, String password, String agent) {
Token tokenuser=new Token();
User user =userDao.doLogin(username,password);
if (user!=null){
//创建token
String token=createTiken(agent);
System.out.println("token:*******"+token);
//保存token和用户信息
save(token,user);
//设置token类属性值
tokenuser.setCode("200");
tokenuser.setMessage("ok");
tokenuser.setToken(token);
}else {
tokenuser.setCode("403");
tokenuser.setMessage("用户名或密码错误");
tokenuser.setToken(null);
//tokenuser.setT(null);
}
return tokenuser;
}
token保存至cookie:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登录</title>
<!-- <script></script>必须写双标签 -->
<script src="js/jquery-3.6.0.js"></script>
</head>
<body>
<form id="form1">
用户名:<input type="text" name="username" id="username"/></br>
密码:<input type="password" name="password" id="username"/></br>
<input type="button" id="btn" value="提交"/>
</form>
<button id="getcookie">获取cookies</button>
<div id="#mes"></div>
<script type="text/javascript">
$("#btn").click(function () {
// var cookies=document.cookie;
// //alert("old:"+cookies);
// console.log("old:"+cookies);
var log_info=$("#form1").serialize();
// console.log(log_info);
$.ajax({
url:"http://localhost:8080/redis01/loginInfo",
type:"post",
data:log_info,
dataType:"json",
success:function (data) {
if (data.code="200"&&data.message=="ok") {
alert("登录成功");
//设置cookie
var token=data.token;
var date=new Date();
// var cookies=document.cookie;
// alert("old:"+document.cookie);
//输出当前cookie
console.log("old:"+document.cookie);
//获取两小时后的时间,用作token有效时间
date.setSeconds(date.getSeconds()+2*60*60);
//console.log(data.token);
//console.log(token);
//将token令牌和有效时间保存到cookie中
document.cookie="token="+token+"; expires="+date.toGMTString();
// alert(document.cookie);
console.log("new:"+document.cookie);
// location.href="welcome.html";
}else {
$("#mes").html(data.message);
}
},
error:function (data) {
alert("请求失败");
}
});
});
$("#getcookie").click(function () {
var cookies=document.cookie;
console.log("click:"+cookies);
});
</script>
</body>
</html>
前端向后端请求时,携带token令牌:
法一:设置请求头
$.ajax(
url:""
....
headers: {
token: localStorage.token
}
)
法二:
在配置跨域filter中加上
//是否携带cookie
resp.setHeader("Access-Control-Allow-Credentials","ture");
Token置换
当token时长截止时,token自动置换
https://blog.csdn.net/weixin_46101839/article/details/115268245置换token