Token生成并验证
Token是服务端生成的一串字符串,以作客户端进行请求的一个令牌(可以理解为一个字符串),当第一次登录后,服务器生成一个Token,便将此Token返回给客户端,以后客户端只需带上这个Token前来请求数据即可,无需再次带上用户名和密码,(一般用户名和密码都被存在生成的字符串中,在服务器拿到这串字符串然后解析会得到传入的用户名和密码)。
TokenUtils
pom.xml
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.7.0</version>
</dependency>
整个生成token的流程,生成,解密。
在 createJWT方法中传入的info传入的是json格式的字符串,在generalSubject方法中我对需要生成的字段做的json处理。传入的id和ttlMillis可自自定义。
package com.temp.template.util;
import com.alibaba.fastjson.JSONObject;
import com.temp.template.entitydata.UxxVO;
import com.temp.template.global.ConfigConstant;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.stereotype.Component;
import java.util.*;
/**
* @Author y
* @Datetime 2021/8/1 2:42
*/
@Component
public class TokenUtil {
/**
* 用户登录成功后生成Jwt
* 使用Hs256算法 私匙使用用户密码
*
* @param id 标识
* @param info 登录成功的user对象
* @param ttlMillis jwt过期时间
* @return
*/
public static String createJWT(String id, String info, long ttlMillis) {
//指定签名的时候使用的签名算法,也就是header那部分,jjwt已经将这部分内容封装好了。
SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
//生成JWT的时间
long nowMillis = System.currentTimeMillis();
Date now = new Date(nowMillis);
//创建payload的私有声明(根据特定的业务需要添加,如果要拿这个做验证,一般是需要和jwt的接收方提前沟通好验证方式的)
//生成签名的时候使用的秘钥secret,这个方法本地封装了的,一般可以从本地配置文件中读取,切记这个秘钥不能外露。
//它就是你服务端的私钥,在任何场景都不应该流露出去。一旦客户端得知这个secret, 那就意味着客户端是可以自我签发jwt了。
String key = ConfigConstant.TOKEN_KEY;
//生成签发人
// String subject = user.getUserMailAddress();
//下面就是在为payload添加各种标准声明和私有声明了
//这里其实就是new一个JwtBuilder,设置jwt的body
JwtBuilder builder = Jwts.builder()
//如果有私有声明,一定要先设置这个自己创建的私有的声明,这个是给builder的claim赋值,一旦写在标准的声明赋值之后,就是覆盖了那些标准的声明的
// .setClaims(claims)
//设置jti(JWT ID):是JWT的唯一标识,根据业务需要,这个可以设置为一个不重复的值,主要用来作为一次性token,从而回避重放攻击。
.setId(id)
//iat: jwt的签发时间
.setIssuedAt(now)
//代表这个JWT的主体,即它的所有人,这个是一个json格式的字符串,可以存放什么userid,roldid之类的,作为什么用户的唯一标志。
.setSubject(info)
//设置签名使用的签名算法和签名使用的秘钥
.signWith(signatureAlgorithm, key);
if (ttlMillis >= 0) {
long expMillis = nowMillis + ttlMillis;
Date exp = new Date(expMillis);
//设置过期时间
builder.setExpiration(exp);
}
return builder.compact();
}
/**
* Token的解密
*
* @param token 加密后的token
* @return
*/
public static Claims parseJWT(String token) {
//签名秘钥,和生成的签名的秘钥一模一样
String key = ConfigConstant.TOKEN_KEY;
//得到DefaultJwtParser
Claims claims = Jwts.parser()
//设置签名的秘钥
.setSigningKey(key)
//设置需要解析的jwt
.parseClaimsJws(token).getBody();
return claims;
}
// public static void main(String[] args) {
// TokenUtil jwTutil = new TokenUtil();
// Claims claims = jwTutil.parseJWT("eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiJ0ZW1wbGF0ZV93ZWIiLCJpYXQiOjE2Mjc4NDI3MTMsInN1YiI6IntcInV4eDAwMlwiOlwiXFx1MDAxOVxcdTAwMURcXHUwMDEyLD1MXFx1MDAxMlxcdTAwMThcXHUwMDFDXFx1MDAxRVxcdTAwMUZcXHUwMDE2NFxcdTAwMTdcXHUwMDE5PlxcdTAwMDZcXHUwMDA1Q1xcdTAwMUM_XFx1MDAxNlxcdTAwMUVcXHUwMDAxTDw0QUFfNVxcdTAwMTJcIixcInV4eDAwMVwiOlwiYWRtaW5cIixcInV4eDAwNFwiOlwiMTU4ODIxNzY5ODFcIixcInV4eDAwM1wiOlwi6JKy5L-KXCIsXCJ1eHgwMDZcIjpcIjIwMjEtMDgtMDIgMDA6MDc6MDBcIixcInV4eDAwNVwiOlwiMzI5Mjg5MzA5QHFxLmNvbVwiLFwieHh6MDAxXCI6XCIzZGM0YTRjNS1jMzc4LTQ0MDAtYmRlNi0xNmUzMDhhYTA1YTRcIn0iLCJleHAiOjE2MjgwMjI3MTN9.uJafuWBNe8DCJ2dwyWs6qN-GSdKvUfeI6INrDFbEVzU");
// String subject = claims.getSubject();
// Message messgae = JSON.parseObject(subject, Message.class);
// System.out.println(JSON.toJSONString(messgae));
// }
/**
* 校验token
* 在这里可以使用官方的校验
*
* @param token
* @return
*/
public static Boolean isVerify(String token) {
try {
//得到DefaultJwtParser
Claims claims = Jwts.parser()
//设置签名的秘钥
.setSigningKey(ConfigConstant.TOKEN_KEY)
//设置需要解析的jwt
.parseClaimsJws(token).getBody();
return false;
} catch (Exception e) {
return false;
}
}
public String generalSubject(UxxVO uxxVO) {
JSONObject jo = new JSONObject();
jo.put("xxz001", uxxVO.getXxz001());
jo.put("uxx001", uxxVO.getUxx001());
jo.put("uxx002", uxxVO.getUxx002());
jo.put("uxx003", uxxVO.getUxx003());
jo.put("uxx004", uxxVO.getUxx004());
jo.put("uxx005", uxxVO.getUxx005());
jo.put("uxx006", uxxVO.getUxx006());
jo.put("uxx008", uxxVO.getUxx008());
return jo.toJSONString();
}
}
生成
第一步生成:在用户登录的时候创建token,根据登录信息,将需要的信息转成json格式的字符串,调用createJWT方法
/**
* 用户登录
*
* @param uxxDTO
* @return
*/
@Override
public ResponseModel getLogin(UxxDTO uxxDTO) {
UxxVO uxxVO = getLoginVerificationPassWord(uxxDTO);
if (uxxVO != null) {
uxxExtDAO.getUpdateUserLastLoginTime(uxxVO.getXxz001());
Message message = generateToken(uxxVO);
return ResponseModelGenerator.genSuccessResponseModel(TipConstant.LOGIN_SUCCESS, message);
}
return ResponseModelGenerator.genSuccessResponseModel(TipConstant.LOGIN_NOT_MATCH);
}
/**
* 生成token
*
* @param uxxDTO
* @return
*/
private Message generateToken(UxxVO uxxVO) {
String info = tokenUtil.generalSubject(uxxVO);
try {
String token = tokenUtil.createJWT(ConfigConstant.TOKEN_ID_WEB, info, ConfigConstant.EXPIRE_DATE);
Message message = new Message();
message.setXxz001(uxxVO.getXxz001());
message.setUxx001(uxxVO.getUxx001());
message.setUxx002(uxxVO.getUxx002());
message.setUxx003(uxxVO.getUxx003());
message.setUxx004(uxxVO.getUxx004());
message.setUxx005(uxxVO.getUxx005());
message.setUxx006(uxxVO.getUxx006());
message.setUxx007(uxxVO.getUxx007());
message.setUxx008(uxxVO.getUxx008());
message.setToken(token);
return message;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
第二部验证
将生成的token复制到TokenUtils中,我写了一个main方法,调用parseJWT解密方法。
debug执行
可以看到token信息被解密,这样子就可以拿到自己想要值了。
以上就是生成token信息并解密的全部过程,对于一些小白来说,不知道怎么去使用,下面我稍微的细说一下。
我们用postman测试,将token信息复制到头部,名称为“token”,值为刚刚登陆成功后生成的toekn值,复制过来即可。
在后端我们用的是拦截器,在拦截器的preHandle方法中(preHandle为拦截的默认可重写方法),调用头部为token的值 (String token = request.getHeader(“token”);),可以直接拿到token的信息。
以上步骤我们登陆成功后,拿到token并验证成功。并将值存在Message类中。
这样子我们就能直接取Message类中的所有数据
以上就是简单的解密后使用token信息查询数据
大晚上写的,困啦,逻辑很混乱,但是八九不离十,不好的多多指出。