Skip to content

Commit

Permalink
http连接器:支持绵阳政务的sha256withrsa加密
Browse files Browse the repository at this point in the history
  • Loading branch information
LeonYoah committed Jun 26, 2024
1 parent 830bca1 commit 1774de9
Show file tree
Hide file tree
Showing 14 changed files with 658 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,7 @@ public HttpResponse doPost(
if (MapUtils.isNotEmpty(headers)){
contentType = headers.get("Content-Type");
}
//处理params位置
//处理params位置 ,如果非form表单请求,那么将params拼接的url里面
if (APPLICATION_JSON.equals(contentType)) {
// Create access address
URIBuilder uriBuilder = new URIBuilder(url);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ public class encryptConstant {
public static final String BODY_SIGN_BASE64 = "BODY-SIGN-BASE64";
//HeaderWWGSHA256Strategy
public static final String HEADER_WWG_SHA256 = "HEADER-WWG-SHA256";
//SHA256_WITH_RSA
public static final String SHA256_WITH_RSA = "SHA256-RSA";

//其他
public static final String SEMICOLON = ";";
Expand Down Expand Up @@ -51,6 +53,14 @@ public class encryptConstant {
public static final String LOGIN_ID = "loginid";
public static final String PASSWORD = "password";
public static final String TOKEN = "token";
//biz_content
public static final String BIZ_CONTENT = "biz_content";
//request_id
public static final String REQUEST_ID = "request_id";
//ACCESS_KEY
public static final String ACCESS_KEY = "access_key";
//encrypt_biz_content
public static final String ENCRYPT_BIZ_CONTENT = "encrypt_biz_content";



Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
import org.apache.seatunnel.connectors.seatunnel.http.source.encrypt.Factory.DefaultEncryptStrategyFactory;
import org.apache.seatunnel.connectors.seatunnel.http.source.encrypt.Factory.EncryptStrategyFactory;
import org.apache.seatunnel.connectors.seatunnel.http.util.EncryptUtil;
import org.apache.seatunnel.connectors.seatunnel.http.util.SecurityUtil;
import org.apache.seatunnel.connectors.seatunnel.http.util.TimeUtils;
import org.apache.seatunnel.shade.com.fasterxml.jackson.core.JsonProcessingException;
import org.apache.seatunnel.shade.com.fasterxml.jackson.databind.JsonNode;
Expand All @@ -59,6 +60,7 @@
import java.util.stream.Collectors;

import static org.apache.seatunnel.connectors.seatunnel.http.client.HttpClientProvider.APPLICATION_JSON;
import static org.apache.seatunnel.connectors.seatunnel.http.constants.encryptConstant.*;
import static org.apache.seatunnel.connectors.seatunnel.http.source.encrypt.EncryptRequest.handleHikvisionApi;

@Slf4j
Expand Down Expand Up @@ -565,22 +567,63 @@ private void executeRequest(Collector<SeaTunnelRow> output,Map<String, String> p

log.info("开始加工返回结果...");

if (MapUtils.isNotEmpty(this.httpParameter.getParamsEncrypt())&& "RSA".equals(this.httpParameter.getParamsEncrypt().get("encrypt_type"))){
String privateKey = this.httpParameter.getParamsEncrypt().get("privateKey");
Map<String, String> contentMap = JsonUtils.toMap(responseString);
String data = contentMap.get("data");
responseString = EncryptUtil.decryptByPrivateKey(data, privateKey);
if (StringUtils.isBlank(responseString)){
log.error("接口请求异常: request url:[{}], request headers:[{}], request param:[{}], request body:[{}],http response status code:[{}], content:[{}]",
url,
encryptHeaders,
encryptParams,
encryptBody,
response.getCode(),
responseString);
throw new SeaTunnelException("未正确获取到RSA加密数据");
if (MapUtils.isNotEmpty(this.httpParameter.getParamsEncrypt())) {

if ("RSA".equals(this.httpParameter.getParamsEncrypt().get(ENCRYPT_TYPE))){
String privateKey = this.httpParameter.getParamsEncrypt().get("privateKey");
Map<String, String> contentMap = JsonUtils.toMap(responseString);
String data = contentMap.get(DATA);
responseString = EncryptUtil.decryptByPrivateKey(data, privateKey);
if (StringUtils.isBlank(responseString)){
log.error("接口请求异常: request url:[{}], request headers:[{}], request param:[{}], request body:[{}],http response status code:[{}], content:[{}]",
url,
encryptHeaders,
encryptParams,
encryptBody,
response.getCode(),
responseString);
throw new SeaTunnelException("未正确获取到RSA加密数据");
}
} else if ("SHA256-RSA".equals(this.httpParameter.getParamsEncrypt().get(ENCRYPT_TYPE))) {
String access_key = this.httpParameter.getParams().get(ACCESS_KEY);
String data= "";
try {
data = JsonUtils.stringToJsonNode(responseString).get("biz_data").get("data").asText();;
} catch (Exception e) {
log.error("接口请求异常: request url:[{}], request headers:[{}], request param:[{}], request body:[{}],http response status code:[{}], content:[{}]",
url,
encryptHeaders,
encryptParams,
encryptBody,
response.getCode(),
responseString);
throw new SeaTunnelException("未正确获取数据,请检查返回格式是否满足 $.biz_data.data");
}
responseString = data;
if ( Boolean.parseBoolean(this.httpParameter.getParamsEncrypt().get(ENCRYPT_BIZ_CONTENT))){
try {
responseString = SecurityUtil.decrypt(data, access_key);
} catch (Exception e) {
log.error("接口请求异常: request url:[{}], request headers:[{}], request param:[{}], request body:[{}],http response status code:[{}], content:[{}]",
url,
encryptHeaders,
encryptParams,
encryptBody,
response.getCode(),
responseString);
throw new SeaTunnelException("非法值,无法解密RSA-SHA256的数据");
}
}

}
}







DocumentContext context = JsonPath.parse(responseString);
// responseString如果是个空数组,会影响processAddition,空json没问题
//params追加
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,9 @@
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

import static org.apache.seatunnel.connectors.seatunnel.http.constants.encryptConstant.*;
import static org.apache.seatunnel.connectors.seatunnel.http.util.SingUtil.sign;
import static org.apache.seatunnel.connectors.seatunnel.http.util.SignUtil.sign;

@Slf4j
public class EncryptRequest {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ public interface EncryptStrategy {

Map<String, String> encryptHeader(Map<String, String> headers, Map<String, String> headerEncrypt, String body) throws SeaTunnelException;

Map<String, String> encryptParam(Map<String, String> params, Map<String, String> paramsEncrypt) throws SeaTunnelException;
Map<String, String> encryptParam(Map<String, String> params, Map<String, String> paramsEncrypt) throws Exception;
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ public EncryptStrategy create(String encryptType) {
return new BodySignBase64Strategy();
case HEADER_WWG_SHA256:
return new HeaderWWGSHA256Strategy();
case SHA256_WITH_RSA:
return new ParamsSHA256withRSAStrategy();
default:
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import java.util.Map;

import static org.apache.seatunnel.connectors.seatunnel.http.constants.encryptConstant.*;
import static org.apache.seatunnel.connectors.seatunnel.http.util.SingUtil.sign;
import static org.apache.seatunnel.connectors.seatunnel.http.util.SignUtil.sign;

public class BodySignMd5Strategy implements EncryptStrategy {
@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package org.apache.seatunnel.connectors.seatunnel.http.source.encrypt.impl;

import org.apache.commons.lang3.StringUtils;
import org.apache.seatunnel.common.utils.JsonUtils;
import org.apache.seatunnel.common.utils.SeaTunnelException;
import org.apache.seatunnel.connectors.seatunnel.http.source.encrypt.EncryptStrategy;
import org.apache.seatunnel.connectors.seatunnel.http.util.EncryptUtil;
import org.apache.seatunnel.connectors.seatunnel.http.util.SecurityUtil;

import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.Signature;
import java.security.spec.KeySpec;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.*;

import static org.apache.seatunnel.connectors.seatunnel.http.constants.encryptConstant.*;

public class ParamsSHA256withRSAStrategy implements EncryptStrategy {
@Override
public void encryptBody(String body, Map<String, Object> bodyMap, Map<String, String> bodyEncrypt, Map<String, String> params) throws SeaTunnelException {

}

@Override
public Map<String, String> encryptHeader(Map<String, String> headers, Map<String, String> headerEncrypt, String body) throws SeaTunnelException {
return headers;
}

@Override
public Map<String, String> encryptParam(Map<String, String> params, Map<String, String> paramsEncrypt) throws Exception {
Map<String, String> encryptParams = JsonUtils.toMap(JsonUtils.toJsonString(params));
String biz_content = params.get(BIZ_CONTENT);
String access_key = params.get(ACCESS_KEY);
String privateKey = paramsEncrypt.get(PRIVATE_KEY);
String decrypt_biz_content = paramsEncrypt.get(ENCRYPT_BIZ_CONTENT);


if (StringUtils.isBlank(privateKey) || StringUtils.isBlank(biz_content) || StringUtils.isBlank(access_key) || StringUtils.isBlank(decrypt_biz_content)){
throw new SeaTunnelException("privateKey, biz_content ,access_key, encrypt_biz_content 不能为空");
}
if (Boolean.parseBoolean(decrypt_biz_content)){
biz_content = SecurityUtil.encrypt(biz_content, access_key);
}
//流水号
String request_id = UUID.randomUUID().toString().replaceAll("-", "").substring(0, 20);
//请求时间戳
String timestamp = String.valueOf(System.currentTimeMillis());

encryptParams.put(BIZ_CONTENT, biz_content);
encryptParams.put(REQUEST_ID, request_id);
encryptParams.put(TIMESTAMP, timestamp);
String source = generateSignSource(encryptParams);
String sign = sign2(source, privateKey);
encryptParams.put(SIGN, sign);

return encryptParams;
}

private String sign2(String source, String keystore) throws Exception {

PrivateKey privateKey = null;
String sign = null;
// Base64解码私钥数据
byte[] encodedKey = Base64.getDecoder().decode(keystore);
KeySpec keySpec = new PKCS8EncodedKeySpec(encodedKey);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
privateKey = keyFactory.generatePrivate(keySpec);

if (privateKey != null) {
//签名
Signature signature = Signature.getInstance("SHA256withRSA");
signature.initSign(privateKey);
signature.update(source.getBytes());
byte[] signed = signature.sign();
//取base64,得到签名串
sign = Base64.getEncoder().encodeToString(signed);
}
return sign;
}

private String generateSignSource(Map params) {
Set<String> keySet = params.keySet();
List<String> keys = new ArrayList<String>();
for (String key : keySet) {
if (params.get(key) != null && StringUtils.isNotBlank(params.get(key).toString())) {
keys.add(key);
}
}
Collections.sort(keys);
StringBuilder builder = new StringBuilder();
for (int i = 0, size = keys.size(); i < size; i++) {
String key = keys.get(i);
Object value = params.get(key);
builder.append(key);
builder.append("=");
builder.append(value);
//拼接时,不包括最后一个&字符
if (i != size - 1) {
builder.append("&");
}
}
return builder.toString();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package org.apache.seatunnel.connectors.seatunnel.http.util;

import sun.misc.BASE64Decoder;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;


/**
* @author lyb
* @version v1.0.0
* @description AES加密工具
* @date 2019-01-14
*/
public class SecurityUtil {


public static String encrypt(String data,String key) throws Exception
{
try {

Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
int blockSize = cipher.getBlockSize();

byte[] dataBytes = data.getBytes("UTF-8");
int plaintextLength = dataBytes.length;
if (plaintextLength % blockSize != 0) {
plaintextLength = plaintextLength + (blockSize - (plaintextLength % blockSize));
}
byte[] plaintext = new byte[plaintextLength];
System.arraycopy(dataBytes, 0, plaintext, 0, dataBytes.length);
SecretKeySpec keyspec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
IvParameterSpec ivspec = new IvParameterSpec(key.getBytes("UTF-8"));
cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);
byte[] encrypted = cipher.doFinal(plaintext);
return new sun.misc.BASE64Encoder().encode(encrypted);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public static String decrypt(String data,String key) throws Exception
{
try
{
byte[] encrypted1 = new BASE64Decoder().decodeBuffer(data);
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
SecretKeySpec keyspec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
IvParameterSpec ivspec = new IvParameterSpec(key.getBytes("UTF-8"));
cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec);
byte[] original = cipher.doFinal(encrypted1);
String originalString = new String(original,"UTF-8");
// String str=new String(originalString.getBytes("ISO-8859-1"),"GBK");
return originalString;
}
catch (Exception e) {
e.printStackTrace();
return null;
}
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import static org.apache.seatunnel.connectors.seatunnel.http.constants.encryptConstant.SIGN;

@Slf4j
public class SingUtil {
public class SignUtil {
public static String sign(Map<String, Object> params, String secretKey) {
String signStr = params.keySet().stream()
.filter(key -> !SIGN.equals(key))
Expand Down
Loading

0 comments on commit 1774de9

Please sign in to comment.