Token的对称与非对称加密

JWT生成Token

Token在日常服务中使用频率非常高,生成Token的方式也非常多,目前使用最广泛的方法是使用JWT生成Token。使用JWT可以选择不同的加密方式保障Token的安全,并且可以自定义Token携带的信息以便于后台验证,生成的Token还能保存在前端,不需要消耗后端服务器资源。

JWT加密方式

  1. 对称加密 ,对称加密即加密解密都使用同一个密钥,HS256加密方式就是用户定义一个密钥(sercret),加密时将密钥与Token中存储用户信息的map生成token。
  2. 非对称加密 ,非对称使用公共/私钥对: 标识提供方采用私钥生成签名, JWT 的使用方获取公钥以验证签名。由于公钥 (与私钥相比) 不需要保护, 因此大多数标识提供方使其易于使用方获取和使用 (通常通过一个元数据URL)。

两种加密方法实现

-引入依赖

   <dependency>
     <groupId>com.nimbusds</groupId>
      <artifactId>nimbus-jose-jwt</artifactId>
      <version>6.0</version>
  </dependency>

对称加密

public class TokenUtils {

/**
 * 密匙
 */

private static final byte[] secret = "geibosssoftsfdjsikolkjikolkijswm".getBytes();


//生成一个token
public static String creatTokenHS256(Map<String,Object> payloadMap) throws JOSEException {

    /**
     * JWSHeader参数:加密算法法则
     *
     * JWSAlgorithm:类里面有所有的加密算法法则,直接调用。
     */
    JWSHeader jwsHeader = new JWSHeader(JWSAlgorithm.HS256);

    //建立一个载荷Payload
    Payload payload = new Payload(new JSONObject(payloadMap));

    //将头部和载荷结合在一起
    JWSObject jwsObject = new JWSObject(jwsHeader, payload);

    //建立一个密匙

    JWSSigner jwsSigner = new MACSigner(secret);

    //签名
    jwsObject.sign(jwsSigner);

    //生成token
    return jwsObject.serialize();

}

public static Map<String,Object> validHS256(String token) throws ParseException, JOSEException {
// 解析token
    JWSObject jwsObject = JWSObject.parse(token);
    //建立一个解锁密匙
    JWSVerifier jwsVerifier = new MACVerifier(secret);
    return verify(jwsObject, jwsVerifier);
}


//验证token信息
private static Map<String,Object> verify(JWSObject jwsObject,JWSVerifier jwsVerifier) throws JOSEException {
    Map<String, Object> resultMap = new HashMap<>();
    //获取到载荷
    Payload payload=jwsObject.getPayload();
    //判断token
    if (jwsObject.verify(jwsVerifier)) {
        resultMap.put("Result", 0);
        //载荷的数据解析成json对象。
        JSONObject jsonObject = payload.toJSONObject();
        resultMap.put("data", jsonObject);
        //判断token是否过期
        if (jsonObject.containsKey("exp")) {
            Long expTime = Long.valueOf(jsonObject.get("exp").toString());
            Long nowTime = DateUtils.getTime();
            //判断是否过期
            if (nowTime > expTime) {
                //已经过期
                resultMap.clear();
                resultMap.put("Result", 2);
            }
        }
    }else {
        resultMap.put("Result", 1);
    }
    return resultMap;
}

}

非对称加密

public class JwtUtils {

/**
 * 创建加密key
 */
public static RSAKey getKey() throws JOSEException {
    RSAKeyGenerator rsaKeyGenerator = new RSAKeyGenerator(2048);
    RSAKey rsaJwk = rsaKeyGenerator.generate();
    System.out.println("加密key是" + rsaJwk);
    return rsaJwk;
}

/**
 * @param payloadMap token的主题部分
 * @param rsaJwk     rsa加密密钥
 * @return 加密后的token
 * @throws JOSEException
 */
public static String creatToken(Map<String, Object> payloadMap, RSAKey rsaJwk) throws JOSEException {
    //私密钥匙
    JWSSigner signer = new RSASSASigner(rsaJwk);
    //构建token主体
    JWSObject jwsObject = new JWSObject(
            new JWSHeader.Builder(JWSAlgorithm.RS256).keyID(rsaJwk.getKeyID()).build(),
            new Payload(new JSONObject(payloadMap))
    );
    //进行加密
    jwsObject.sign(signer);
    //生成token
    String token = jwsObject.serialize();
    return token;
}

/**
 * @param token  相关token
 * @param rsaJwk 相关密钥
 * @return
 * @throws ParseException
 * @throws JOSEException
 */
public static Map<String, Object> validToken(String token, RSAKey rsaJwk) throws ParseException, JOSEException {
    //获取到公钥
    RSAKey rsaKey = rsaJwk.toPublicJWK();
    JWSObject jwsObject = JWSObject.parse(token);
    JWSVerifier jwsVerifier = new RSASSAVerifier(rsaKey);
    //验证数据
    Map<String, Object> tokenMap = new HashMap<>();
    //记录token主体信息
    Payload payload = jwsObject.getPayload();
    //判断token是否合法
    if (jwsObject.verify(jwsVerifier)) {
        tokenMap.put("Result", 0);
        //将token数据转为json对象
        JSONObject jsonObject = payload.toJSONObject();
        //将token数据存入map中
        tokenMap.put("Data", jsonObject);
        //判断token是否过期
        if (jsonObject.containsKey("exp")) {
            //获取token保存的过期时间
            Long expTime = Long.valueOf(jsonObject.get("exp").toString());
            //获取当前时间戳
            Long nowTime = DateUtils.getTime();
            //判断是否过期
            if (nowTime > expTime) {
                //清除token信息,将其标志为过期
                tokenMap.clear();
                tokenMap.put("Result", 2);
            }
        }
    } else {
        //将token标志为不合法
        tokenMap.put("Result", 1);
    }
    return tokenMap;
}

//从token获取相关参数
public static Object get(String token, RSAKey rsaJwk ,String fieldName){
    try {
        Map<String, Object> validMap = JwtUtils.validToken(token,rsaJwk);
        JSONObject jsonObject = (JSONObject) validMap.get("Data");
        if (jsonObject.get(fieldName) == null){
            return "该参数不存在";
        }else{
            return jsonObject.get(fieldName);
        }
    }catch (ParseException e){
        e.printStackTrace();
    }catch (JOSEException e){
        e.printStackTrace();
    }
    return null;
}

}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值