springboot(五):采用RSA对用户登录凭证token进行生成和解析

我们都知道http请求是无状态的,所以需要通过cookie在客户端记录状态或者通过session在服务器端记录状态,而这一般就是通过token来维持这种状态验证的。
在这里插入图片描述
那么问题来了,这个token该怎么生成和解析呢。
一般token是可以携带一些信息的,用户登录成功后,假设我们将用户id+时间戳通过RSA公钥加密生成token返回给用户。后面用户调用其他接口都携带该token向服务端发起请求。这个时候服务端可以在拦截器对该token进行RSA私钥解密,从而得到原来的用户id+时间戳。这就是验证和解析token的一个完整过程。下面提供一个RSA工具类,可以直接使用。

RSA工具类



import org.apache.tomcat.util.codec.binary.Base64;

import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;

import javax.crypto.Cipher;


public class RSAUtils {

    // 数字签名,密钥算法
    private static final String RSA_KEY_ALGORITHM = "RSA";

    // 数字签名签名/验证算法
    private static final String SIGNATURE_ALGORITHM = "MD5withRSA";

    // RSA密钥长度
    private static final int KEY_SIZE = 1024;

    private static final String PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC92uYItLaBOwOf4EmafzvDtDrBnV1bA6wagEUCCnLMovsv1OUSBu8dqq7n1D/shlMFBm007zIPRNhHQWi41SxNoyBSGvKLO2Y2QU637NWVvH31Be8qaP+B7tq9YFPsBszxGie1DB8OMHthmd56VSHtY394ipW6h60n46x6WZfoxQIDAQAB";
    private static final String PRIVATE_KEY = "MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAL3a5gi0toE7A5/gSZp/O8O0OsGdXVsDrBqARQIKcsyi+y/U5RIG7x2qrufUP+yGUwUGbTTvMg9E2EdBaLjVLE2jIFIa8os7ZjZBTrfs1ZW8ffUF7ypo/4Hu2r1gU+wGzPEaJ7UMHw4we2GZ3npVIe1jf3iKlbqHrSfjrHpZl+jFAgMBAAECgYEAgWEMBADKonSJ+siIwB1Wp/5JUCoiNWTiQskIveRK6UNj8+ucE1XgW5I2UUvmKBQ9vR3tC/a5YYhj7uMXL2YuIqmf0xhz4xeiM92uaTQBdd964gBR4q+HEOWkqbahM6e0Gi4bu7VrzuCQiw1BbEHh24qDNZCK1A2jVz3syl96K8ECQQDi1MmZ8SxgCUUjZMGbTmrbE0+SI9fyPjqQJbQTAu3zAFcOiRGIsz4BYLyY/y9rMcMYvQWTl4KSP9ztPKZB706VAkEA1kTeUTG6mH8rwbBlSfmdXhW0qgDI/UDz1pE53kCUduh6Oy9VnReVn38A+zqqJQp2JevFaR3GpPsU/mGcenQVcQJBAM7EYTEuouC4Eon84m8LwGQK6lGw0rxC9WdItylNVlJYUQMy9wTBPxhKciCVHUh9h/YY9+heB+wAwwaObo9T8TECQQCF0+vbYKj/+GX3CtqosoxUqE/34pemfjwOJxSyuTlBb4BwmObrQEDGpseRIpoEmp0ioDjjp6JbhyscmxDl9r0xAkA3gzO20lAT87kjapPhlefBvIlHv9LJLX7rPVqpguMvfVm5xx4uUA0W/jvIzDMVJcB0fT02fTPKRJhBgS1Lrz/7";





    /**
     * 初始化RSA密钥对
     *
     * @return RSA密钥对
     * @throws Exception 抛出异常
     */
    private static Map<String, String> initKey() throws Exception {
        KeyPairGenerator keygen = KeyPairGenerator
                .getInstance(RSA_KEY_ALGORITHM);
        SecureRandom secrand = new SecureRandom();
        secrand.setSeed("zlife".getBytes());// 初始化随机产生器
        keygen.initialize(KEY_SIZE, secrand); // 初始化密钥生成器
        KeyPair keys = keygen.genKeyPair();
        String pub_key = Base64.encodeBase64String(keys.getPublic().getEncoded());
        String pri_key = Base64.encodeBase64String(keys.getPrivate().getEncoded());
        Map<String, String> keyMap = new HashMap<>();
        keyMap.put("publicKey", pub_key);
        keyMap.put("privateKey", pri_key);
        System.out.println("公钥:" + pub_key);
        System.out.println("私钥:" + pri_key);
        return keyMap;
    }

    /**
     * 得到公钥
     *
     * @param keyMap RSA密钥对
     * @return 公钥
     * @throws Exception 抛出异常
     */
    public static String getPublicKey(Map<String, String> keyMap) throws Exception {
        return keyMap.get("publicKey");
    }

    /**
     * 得到私钥
     *
     * @param keyMap RSA密钥对
     * @return 私钥
     * @throws Exception 抛出异常
     */
    public static String getPrivateKey(Map<String, String> keyMap) throws Exception {
        return keyMap.get("privateKey");
    }

    /**
     * 数字签名
     *
     * @param data    待签名数据
     * @param pri_key 私钥
     * @return 签名
     * @throws Exception 抛出异常
     */
    public static String sign(byte[] data, String pri_key) throws Exception {
        // 取得私钥
        byte[] pri_key_bytes = Base64.decodeBase64(pri_key);
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(pri_key_bytes);
        KeyFactory keyFactory = KeyFactory.getInstance(RSA_KEY_ALGORITHM);
        // 生成私钥
        PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec);
        // 实例化Signature
        Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
        // 初始化Signature
        signature.initSign(priKey);
        // 更新
        signature.update(data);

        return Base64.encodeBase64String(signature.sign());
    }

    /**
     * RSA校验数字签名
     *
     * @param data    数据
     * @param sign    签名
     * @param pub_key 公钥
     * @return 校验结果,成功为true,失败为false
     * @throws Exception 抛出异常
     */
    public boolean verify(byte[] data, byte[] sign, String pub_key) throws Exception {
        // 转换公钥材料
        // 实例化密钥工厂
        byte[] pub_key_bytes = Base64.decodeBase64(pub_key);
        KeyFactory keyFactory = KeyFactory.getInstance(RSA_KEY_ALGORITHM);
        // 初始化公钥
        // 密钥材料转换
        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(pub_key_bytes);
        // 产生公钥
        PublicKey pubKey = keyFactory.generatePublic(x509KeySpec);
        // 实例化Signature
        Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
        // 初始化Signature
        signature.initVerify(pubKey);
        // 更新
        signature.update(data);
        // 验证
        return signature.verify(sign);
    }

    /**
     * 公钥加密
     *
     * @param data    待加密数据
     * @param pub_key 公钥
     * @return 密文
     * @throws Exception 抛出异常
     */
    private static byte[] encryptByPubKey(byte[] data, byte[] pub_key) throws Exception {
        // 取得公钥
        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(pub_key);
        KeyFactory keyFactory = KeyFactory.getInstance(RSA_KEY_ALGORITHM);
        PublicKey publicKey = keyFactory.generatePublic(x509KeySpec);
        // 对数据加密
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        return cipher.doFinal(data);
    }

    /**
     * 公钥加密
     *
     * @param data    待加密数据
     * @param pub_key 公钥
     * @return 密文
     * @throws Exception 抛出异常
     */
    public static String encryptByPubKey(String data, String pub_key) throws Exception {
        // 私匙加密
        byte[] pub_key_bytes = Base64.decodeBase64(pub_key);
        byte[] enSign = encryptByPubKey(data.getBytes(), pub_key_bytes);
        return Base64.encodeBase64String(enSign);
    }

    /**
     * 私钥加密
     *
     * @param data    待加密数据
     * @param pri_key 私钥
     * @return 密文
     * @throws Exception 抛出异常
     */
    private static byte[] encryptByPriKey(byte[] data, byte[] pri_key) throws Exception {
        // 取得私钥
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(pri_key);
        KeyFactory keyFactory = KeyFactory.getInstance(RSA_KEY_ALGORITHM);
        PrivateKey privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
        // 对数据加密
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.ENCRYPT_MODE, privateKey);
        return cipher.doFinal(data);
    }

    /**
     * 私钥加密
     *
     * @param data    待加密数据
     * @param pri_key 私钥
     * @return 密文
     * @throws Exception 抛出异常
     */
    public static String encryptByPriKey(String data, String pri_key) throws Exception {
        // 私匙加密
        byte[] pri_key_bytes = Base64.decodeBase64(pri_key);
        byte[] enSign = encryptByPriKey(data.getBytes(), pri_key_bytes);
        return Base64.encodeBase64String(enSign);
    }

    /**
     * 公钥解密
     *
     * @param data    待解密数据
     * @param pub_key 公钥
     * @return 明文
     * @throws Exception 抛出异常
     */
    private static byte[] decryptByPubKey(byte[] data, byte[] pub_key) throws Exception {
        // 取得公钥
        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(pub_key);
        KeyFactory keyFactory = KeyFactory.getInstance(RSA_KEY_ALGORITHM);
        PublicKey publicKey = keyFactory.generatePublic(x509KeySpec);
        // 对数据解密
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.DECRYPT_MODE, publicKey);
        return cipher.doFinal(data);
    }

    /**
     * 公钥解密
     *
     * @param data    待解密数据
     * @param pub_key 公钥
     * @return 明文
     * @throws Exception 抛出异常
     */
    public static String decryptByPubKey(String data, String pub_key) throws Exception {
        // 公匙解密
        byte[] pub_key_bytes = Base64.decodeBase64(pub_key);
        byte[] design = decryptByPubKey(Base64.decodeBase64(data), pub_key_bytes);
        return new String(design);
    }

    /**
     * 私钥解密
     *
     * @param data    待解密数据
     * @param pri_key 私钥
     * @return 明文
     * @throws Exception 抛出异常
     */
    private static byte[] decryptByPriKey(byte[] data, byte[] pri_key) throws Exception {
        // 取得私钥
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(pri_key);
        KeyFactory keyFactory = KeyFactory.getInstance(RSA_KEY_ALGORITHM);
        PrivateKey privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
        // 对数据解密
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        return cipher.doFinal(data);
    }

    /**
     * 私钥解密
     *
     * @param data    待解密数据
     * @param pri_key 私钥
     * @return 明文
     * @throws Exception 抛出异常
     */
    public static String decryptByPriKey(String data, String pri_key) throws Exception {
        // 私匙解密
        byte[] pri_key_bytes = Base64.decodeBase64(pri_key);
        byte[] design = decryptByPriKey(Base64.decodeBase64(data), pri_key_bytes);
        return new String(design);
    }


    /**
     * @param args
     */
    @SuppressWarnings("static-access")
    public static void main(String[] args) throws Exception {


//        initKey();

        String datastr = "10-"+System.currentTimeMillis();
        System.out.println("待加密数据:\n" + datastr);

        long time = System.currentTimeMillis();
         //公匙加密
        String pubKeyStr = RSAUtils.encryptByPubKey(datastr, PUBLIC_KEY);
        System.out.println("公匙加密结果:\n" + pubKeyStr);
        System.out.println("公匙加密时间:\n" + (System.currentTimeMillis()-time));
        // 私匙解密
        String priKeyStr = RSAUtils.decryptByPriKey(pubKeyStr, PRIVATE_KEY);
        System.out.println("私匙解密结果:\n" + priKeyStr);
        System.out.println("私匙解密时间:\n" + (System.currentTimeMillis()-time));


//
//        // 数字签名
//        String str1 = "汉兵已略地";
//        String str2 = "四面楚歌声";
//        System.out.println("正确的签名:" + str1 + "\n错误的签名:" + str2);
//        String sign = RSAUtils.sign(str1.getBytes(), pri_key);
//        System.out.println("数字签名:\n" + sign);
//        boolean vflag1 = das.verify(str1.getBytes(), Base64.decodeBase64(sign), pub_key);
//        System.out.println("数字签名验证结果1:\n" + vflag1);
//        boolean vflag2 = das.verify(str2.getBytes(), Base64.decodeBase64(sign), pub_key);
//        System.out.println("数字签名验证结果2:\n" + vflag2);

    }
}

特别注意,这里的PUBLIC_KEY和PRIVATE_KEY即公钥和私钥,可以在main函数使用initKey()函数生成。

欢迎关注本人公众号和小程序,谢谢
在这里插入图片描述

在这里插入图片描述

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值