Token生成规则以及工具

来源:互联网 发布:淘宝亲宝贝平台的卖家 编辑:程序博客网 时间:2024/06/17 03:26
Token工具
package com.frank.common.utils;import com.alibaba.fastjson.JSON;import com.frank.common.entity.TokenHeader;import com.frank.common.entity.TokenPlayload;import com.frank.common.entity.User;import java.rmi.server.UID;import java.util.UUID;/** * Description:Token生成工具 * 第一部分我们称它为头部(header),第二部分我们称其为载荷(payload, 类似于飞机上承载的物品),第三部分是签证(signature). * Auth: Frank * Date: 2017-11-02 * Time: 下午 5:05 */public class TokenUtil {    public static final  String TOKEN_AES_KEY = "xiangli8Token";    public static final  String REFREH_TOKEN_AES_KEY = "xiangli8RefreshToken";    public static final  String JWT_TYP = "JWT";    public static final  String JWT_ALG = "AES";    public static final  String JWT_EXP = "30";    public static final  String JWT_ISS = "xiangli8";    /**     * 获得token     * @param data 自定义数据     * @param <T> 自定义数据     * @return     * @throws Exception     */    public static <T> String getToken(T data) throws Exception {        TokenPlayload<T> userTokenPlayload = new TokenPlayload<>();        userTokenPlayload.setExpData(data);        String jwt = createJWT(userTokenPlayload);        return jwt;    }    /**     * 生成jwt的header部分内容     * @return     * @throws Exception     */    private static String tokenHeaderBase64() throws Exception {        TokenHeader tokenHeader = new TokenHeader();        tokenHeader.setTyp(JWT_TYP);        tokenHeader.setAlg(JWT_ALG);        String headerJson = JSON.toJSONString(tokenHeader);        String headerBase64 = Base64Util.encryptBASE64(headerJson.getBytes());        return headerBase64;    }    /**     * 生成jwt的payload部分内容     * @param tokenPlayload     * @param <T>自定义的数据块     * @return     * @throws Exception     */    private static <T> String tokenPayloadBase64(TokenPlayload<T> tokenPlayload) throws Exception {        tokenPlayload.setIss(JWT_ISS);        tokenPlayload.setExp(JWT_EXP);        tokenPlayload.setIat(String.valueOf(System.currentTimeMillis()));        String headerJson =JSON.toJSONString(tokenPlayload);        String headerBase64 = Base64Util.encryptBASE64(headerJson.getBytes());        return headerBase64;    }    /**     * 生成JWT     * @return     */    public static <T> String createJWT(TokenPlayload<T> tokenPlayload) throws Exception {        StringBuilder jwtSb = new StringBuilder();        StringBuilder headerPlayloadSb = new StringBuilder();        String tokenHeaderBase64 = tokenHeaderBase64();        String tokenPayloadBase64 = tokenPayloadBase64(tokenPlayload);        jwtSb.append(tokenHeaderBase64);        jwtSb.append(".");        jwtSb.append(tokenPayloadBase64);        jwtSb.append(".");        headerPlayloadSb.append(tokenHeaderBase64);        headerPlayloadSb.append(tokenPayloadBase64);        String headerPlayloadSalt = SaltUtil.addSalt(headerPlayloadSb.toString());        String key = AesUtil.initKey(TOKEN_AES_KEY+tokenPlayload.getIat());        String  signature = Base64Util.encryptBASE64(AesUtil.encrypt(headerPlayloadSalt.getBytes(),key));        jwtSb.append(signature);        return Base64Util.encryptBASE64(jwtSb.toString().getBytes());    }    /**     * 校验token是否是服务器生成的,以防token被修改     * @param jwtBase64     * @return     * @throws Exception     */    public static <T> boolean verifyJWT(String jwtBase64) throws Exception {        String jwt = new String (Base64Util.decryptBASE64(jwtBase64));        if(!jwt.contains(".")){            return false;        }        String[] jwts = jwt.split("\\.");        if(jwts.length<3){            return false;        }        TokenPlayload tTokenPlayload =  JSON.parseObject(new String(Base64Util.decryptBASE64(jwts[1])),TokenPlayload.class);        String key = AesUtil.initKey(TOKEN_AES_KEY+tTokenPlayload.getIat());        //解析出header跟playload        StringBuilder headerPlayloadSb = new StringBuilder();        headerPlayloadSb.append(jwts[0]);        headerPlayloadSb.append(jwts[1]);        //解析signature        String  headerPlayloadSalt = new String (AesUtil.decrypt(Base64Util.decryptBASE64(jwts[2]),key));        return SaltUtil.verifyPwd(headerPlayloadSb.toString(),headerPlayloadSalt);    }    public static void main(String[] args) throws Exception {        String jwt = getToken(new User(1L,"你是逗逼"));        System.out.println("jwt:"+jwt);        System.out.println("verifyJWT:"+verifyJWT(jwt));    }}
使用说明

1,根据上面生成一个由base64编码的token,该token由Header,Payload,Signature组成。

2,token作为用户请求的标识,客户端保存这token的全部信息。服务端只需要保存token的Signature部分。

3,服务端把token的Signature存于redis和服务器的数据库中。

4,客户端请求的数据附带token,服务端拿到token,首先校验token,以防token伪造。校验规则如下:

4.1,拆分出token的Header,Payload,Signature。4.2,校验Signature,通过token的header和payload生成Signature,看看生成的Signature是否和客户端附带上来的Signature一致。如果一致继续请求操作,不一致则打回操作4.3,查看Signature是否存在服务器的redis和数据库中。如果不存在则打回请求操作

注意:上面涉及的加盐算法和Aes加密请看本人写的其他文章