问题引入
因为http请求是无状态,不携带用户信息的,当用户登录成功后,之后在此与服务器交互时,服务器并不知道是哪个用户发送的请求。
会话跟踪是Web程序中常用的技术,用来跟踪用户的整个会话过程。
给客户端们颁发一个通行证,每人一个,无论谁访问都必须携带自己通行证。
这样服务器就能从通行证上确认客户身份了
token
token是服务端生成的一串字符串,以作客户端进行请求的一个令牌,当第一次登录后,服务器生成一个token便将此token返回给客户端,以后客户端只需带上这个token前来请求数据即可。token保存在客户端,并且进行了加密,保证了数据的安全性.
token过滤器
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ffyc.dormserver.model.Result;
import com.ffyc.dormserver.util.JWTUtil;
import javax.servlet.*;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.PrintWriter;
/*
token验证过滤器
*/
public class AdminTokenFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("token验证过滤器");
HttpServletRequest request =(HttpServletRequest) servletRequest;
String admintoken = request.getHeader("adminToken");//从请求头中获得token
System.out.println(admintoken);//验证token
boolean res = JWTUtil.verify(admintoken);
if(res){
filterChain.doFilter(servletRequest, servletResponse);//离开过滤器,继续向下执行
}else {
//向前端响应
Result result = new Result(401, "token验证失败,请重新登录", null);
PrintWriter writer = servletResponse.getWriter();
writer.write(new ObjectMapper().writeValueAsString(result));
}
}
}
在web.xml中配置
<!--验证token过滤器-->
<filter>
<filter-name>tokenfilter</filter-name>
<filter-class>com.ffyc.dormserver.filter.AdminTokenFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>tokenfilter</filter-name>
<url-pattern>/api/*</url-pattern> <!--请求地址中有api前级的请求,进入到验证token的过滤器-->
</filter-mapping>
public class Admin {
private int id;
private String account;
private String password;
private String gender;
private String phone;
private String adminToken;
public String getAdminToken() {
return adminToken;
}
public void setAdminToken(String adminToken) {
this.adminToken = adminToken;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getAccount() {
return account;
}
public void setAccount(String account) {
this.account = account;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
}
导入工具类
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.ffyc.dormserver.model.Admin;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
* JWT工具类
*/
public class JWTUtil {
/**
* 根据用户id,账号生成token
* @param
* @return
*/
public static String getToken(Admin admin) {
String token = "";
try {
//过期时间 为1970.1.1 0:0:0 至 过期时间 当前的毫秒值 + 有效时间
Date expireDate = new Date(new Date().getTime() + 10000*1000);
//秘钥及加密算法
Algorithm algorithm = Algorithm.HMAC256("ZCEQIUBFKSJBFJH2020BQWE");
//设置头部信息
Map<String,Object> header = new HashMap<>();
header.put("typ","JWT");
header.put("alg","HS256");
//携带id,账号信息,生成签名
token = JWT.create()
.withHeader(header)//设置第一份信息
.withClaim("id",admin.getId())//设置第二部分 载荷 管理员信息
.withClaim("account",admin.getAccount())
.withExpiresAt(expireDate)//设置token有效时间
.sign(algorithm);//设置密钥
}catch (Exception e){
e.printStackTrace();
return null;
}
return token;
}
/**
* 验证token是否有效
* @param token
* @return
*/
public static boolean verify(String token){
try {
//验签
Algorithm algorithm = Algorithm.HMAC256("ZCEQIUBFKSJBFJH2020BQWE");
JWTVerifier verifier = JWT.require(algorithm).build();
DecodedJWT jwt = verifier.verify(token);
return true;
} catch (Exception e) {//当传过来的token如果有问题,抛出异常
return false;
}
}
/**
* 获得token 中playload部分数据,按需使用
* @param token
* @return
*/
public static DecodedJWT getTokenInfo(String token){
return JWT.require(Algorithm.HMAC256("ZCEQIUBFKSJBFJH2020BQWE")).build().verify(token);
}
}