Java编写post请求-入参使用MD5withRSA加密,处理入参

时间:2024-10-25 07:10:57

#1024程序员节|征文#

废话可以不用看:最近经常遇到加密请求,一般都是使用代码处理入参加密后,再复制到apifox请求。但!这次不行了,有个字段很快就过期,还有个时间戳字段也用代码生成的,我这边刚跑起来加密的代码,把时间戳和加密的复制过去正好字段过期,经历了一番过后,手速明显提高,但还是赶在点击发送请求之前字段过期,我觉得还是用脑力节省体力,写个Java一劳永逸。

注:代码逻辑根据实际请求需要更改。需要自取~

代码中有:

1、自动生成RSA密钥 或 使用自己的私钥公钥。

2、私钥对明文签名,公钥对签名验证。

3、13位和17位时间戳。

4、生成随机数字和大小写字母。

5、POST请求地址、入参获取响应值。

package test;
//加密等操作引入
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.util.Base64;
import java.security.KeyFactory;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.security.SecureRandom;
import java.text.SimpleDateFormat;
import java.util.Date;
//POST请求引入
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.io.BufferedReader;
import java.io.InputStreamReader;

public class testP {
    //定义常量-RSA:RSA、ALGORITHM:ALGORITHM、CHAR_SET:数字和大小写字母
    private static final String RSA = "RSA";
    private static final String ALGORITHM = "MD5withRSA";
    private static final String CHAR_SET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
    //已知私钥,生成PrivateKey方式
    public static PrivateKey getPrivateKey(String key) throws Exception {
        byte[] keyBytes = Base64.getDecoder().decode(key);
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(RSA);
        return keyFactory.generatePrivate(keySpec);
    }
    //已知公钥,生成PublicKey方式
    public static PublicKey getPublicKey(String key) throws Exception {
        byte[] keyBytes = Base64.getDecoder().decode(key);
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(RSA);
        return keyFactory.generatePublic(keySpec);
    }
    /**
     * 如果使用自动生成RSA密钥可使用此方法
     * @return
     * @throws NoSuchAlgorithmException
     */
    public static KeyPair generateKeyPair() throws NoSuchAlgorithmException {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(RSA);
        keyPairGenerator.initialize(2048);
        return keyPairGenerator.genKeyPair();
    }
    /**
     * 使用私钥对明文进行签名
     * @param plainText  明文
     * @param privateKey 私钥
     * @return 签名结果
     * @throws Exception 签名异常
     */
    public static String sign(String plainText, PrivateKey privateKey) throws Exception {
        Signature signature = Signature.getInstance(ALGORITHM);
        signature.initSign(privateKey);
        signature.update(plainText.getBytes());
        byte[] signedData = signature.sign();
        return Base64.getEncoder().encodeToString(signedData);
    }
    /**
     * 使用公钥对签名进行验证
     * @param plainText 明文
     * @param signature 签名结果
     * @param publicKey 公钥
     * @return 验证结果,true表示验证通过,false表示验证失败
     * @throws Exception 验证异常
     */
    public static boolean verify(String plainText, String signature, PublicKey publicKey) throws Exception {
        Signature signatureObj = Signature.getInstance(ALGORITHM);
        signatureObj.initVerify(publicKey);
        signatureObj.update(plainText.getBytes());
        byte[] decodedSignature = Base64.getDecoder().decode(signature);
        return signatureObj.verify(decodedSignature);
    }

    public static void main(String[] args) throws Exception {
//        // 自动生成RSA密钥对
//        KeyPair keyPair = generateKeyPair();
//        PrivateKey privateKey = keyPair.getPrivate();
//        PublicKey publicKey = keyPair.getPublic();
        //自己的公钥和私钥转换为PrivateKey可以使用的格式
        String privateKeyString = "你的私钥";
        String publicKeyString = "你的公钥";
        PrivateKey privateKey = getPrivateKey(privateKeyString);
        PublicKey publicKey = getPublicKey(publicKeyString);
        //生成13位和17位时间戳
        long timestamp = System.currentTimeMillis();
        String timestampStr13 = Long.toString(timestamp);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
        String timestampStr17 = sdf.format(new Date());
        String tradeNo ="1111"+timestampStr17+"992211";
        System.out.println("订单号:" + tradeNo);
        //生成随机数字和大小写字母
        SecureRandom random = new SecureRandom();
        StringBuilder sb = new StringBuilder(22);
        for (int i = 0; i < 22; i++) {
            sb.append(CHAR_SET.charAt(random.nextInt(CHAR_SET.length())));
        }
        String nonceStr = sb.toString();
        // 明文plainText:待加密明文
        String authCode = "123456";
        String plainText = "nonceStr="+nonceStr+"&timestamp="+timestampStr13+"&tradeNo="+tradeNo;
        System.out.println("签名前数据:" + plainText);
        // 使用私钥对明文进行签名
        String signature = testP.sign(plainText, privateKey);
        System.out.println("签名结果:" + signature);
        // 使用公钥对签名进行验证
        boolean result = testP.verify(plainText, signature, publicKey);
        System.out.println("验证签名结果:" + result);
        //编写post请求
        try {
            URL url = new URL("http://你的请求链接/ncel");
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("POST");
            conn.setDoOutput(true);
            conn.setDoInput(true);
            // 设置请求头
            conn.setRequestProperty("Content-Type", "application/json");
            // 写入POST数据
            String postData = "{\"nonceStr\":\""+nonceStr+"\",\"sign\":\""+signature+"\",\"timestamp\":\""+timestampStr13+"\",\"tradeNo\":\""+tradeNo+"\"}";
            byte[] outputInBytes = postData.getBytes("UTF-8");
            OutputStream os = conn.getOutputStream();
            os.write(outputInBytes);
            os.close();
            // 获取响应码
            BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            String inputLine;
            StringBuilder response = new StringBuilder();
            while ((inputLine = in.readLine()) != null) {
                response.append(inputLine);
            }
            System.out.println("请求返回值:"+ response);
            in.close();
            // 获取响应状态码,读取响应内容
            int responseCode = conn.getResponseCode();
            if (responseCode == HttpURLConnection.HTTP_OK) {
            }
            //关闭http连接
            conn.disconnect();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

小知识点:Java基础类型

基础类型直接存储值通常存储在栈内存中,使访问速度快。

1、byte:8位有符号整数。
2、short:16位有符号整数。
3、int:32位有符号整数。
4、long:64位有符号整数。
5、float:32位单精度浮点数。
6、double:64位双精度浮点数。
7、char:16位Unicode字符。
8、boolean:用于表示真/假值。

int和long用于数值计算,如计数器、循环索引等。
float和double用于科学计算或者需要精确小数的场景。
char用于处理单个字符,如读取文件中的字符。
boolean用于逻辑运算,如条件判断。

异常是程序运之前,编译期间出实现的错误,这些异常异常往往在运时才能被发现。