Merge remote-tracking branch 'origin/main'

main
陈伟 2 months ago
commit 5fb3078919

@ -0,0 +1,134 @@
using NPOI.POIFS.Crypt.Dsig;
using Org.BouncyCastle.Crypto.Signers;
using System;
using System.Buffers.Text;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Text.Unicode;
using System.Threading.Tasks;
namespace Infrastructure.Helpers
{
public class EncryptionHelper
{
String privateKey = "ABA4354EFAFE944C2F226A3981C7DC70F43BD6053EDA83F4DC274242BBB23CAA";
String publicKey = "04F1BF1BEFD63F16E5DB3BCD32CA5D9A8E8DF7ADD67D6C4F293FB23F7BDA74F52D31B8DDAD03D955D566505A15D8B7DBE83B42378B8E8749C0EB6E2FBC8675838B";
byte[] sm4Key = null;
public EncryptionHelper()
{
}
/// <summary>
/// 获取x-lc-secret
/// </summary>
/// <returns></returns>
public string getxseret()
{
if (sm4Key == null)
{
sm4Key = SM4CryptoHelper.GenerateSM4Key();
}
string publickey = "04D6974E2384ECE39F5ADF1473E4B9B60E0D438A6F701F667C0C88D25BE2F8508A3AAFF9D9500ECFFD8E79B2DE58C024B689B5C207486646EA08A352FBB0016D46";
//十六进制字符串 → 字节数组
byte[] publickeybyte = HexToBytes(publickey);
var encryptdatasm2 = SM2CryptoHelper.Encrypt(publickeybyte, sm4Key);
return Convert.ToBase64String(encryptdatasm2);
}
/// <summary>
/// 数据加密
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
public string Encrypt(byte[] input)
{
if (sm4Key == null)
{
sm4Key = SM4CryptoHelper.GenerateSM4Key();
}
var encryptdatasm4 = SM4CryptoHelper.Encrypt(sm4Key, input);
return Convert.ToBase64String(encryptdatasm4);
}
/// <summary>
/// 数据解密
/// </summary>
/// <param name="x_lc_screte"></param>
/// <param name="output"></param>
/// <returns></returns>
public string Decrypt(byte[] x_lc_screte,byte[] output)
{
byte[] privatekeybyte = HexToBytes(privateKey);
byte[] sm4key = SM2CryptoHelper.Decrypt(privatekeybyte, x_lc_screte);
var decryptdata = SM4CryptoHelper.Decrypt(sm4key, output);
return Encoding.UTF8.GetString(decryptdata);
}
/// <summary>
/// 获取x-lc-token
/// </summary>
/// <param name="certCode"></param>
/// <returns></returns>
/// <exception cref="InvalidOperationException"></exception>
public string GetToken(string certCode)
{
// 获取毫秒级时间戳(.NET 中 Ticks 转换为毫秒)
long timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
//long timestamp = 1751274197662;
// 拼接待签名数据
string needSignData = certCode + timestamp;
byte[] needSignDataByte = Encoding.UTF8.GetBytes(needSignData);
// 4. SM2签名
byte[] signData;
byte[] privatekeybyte = HexToBytes(privateKey);
try
{
signData = SM2CryptoHelper.Sign(privatekeybyte, needSignDataByte);
}
catch (Exception ex)
{
throw new InvalidOperationException("SM2签名失败", ex);
}
// SM2 签名
//byte[] signData = SM2CryptoHelper.Sign(privatekeybyte, needSignDataByte);
// Base64 编码签名(直接使用 Convert
string signDataBase64 = Convert.ToBase64String(signData);
// 生成 token
string token = $"{certCode}.{timestamp}.{signDataBase64}";
return token;
}
/// <summary>
/// 内部转byte方法
/// </summary>
/// <param name="hex"></param>
/// <returns></returns>
/// <exception cref="ArgumentNullException"></exception>
/// <exception cref="ArgumentException"></exception>
public static byte[] HexToBytes(string hex)
{
if (hex == null)
throw new ArgumentNullException(nameof(hex));
if (hex.Length % 2 != 0)
throw new ArgumentException("十六进制字符串长度必须是偶数");
byte[] bytes = new byte[hex.Length / 2];
for (int i = 0; i < bytes.Length; i++)
{
string byteStr = hex.Substring(i * 2, 2);
bytes[i] = Convert.ToByte(byteStr, 16);
}
return bytes;
}
}
}

@ -0,0 +1,266 @@
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.GM;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Digests;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Crypto.Signers;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Math.EC;
using Org.BouncyCastle.Security;
using System;
using System.Text;
namespace Infrastructure.Helpers
{
public class SM2CryptoHelper
{
private static readonly ECDomainParameters DomainParams;
// 国标要求的默认用户ID
private static readonly byte[] DefaultUserId = Encoding.UTF8.GetBytes("1234567812345678");
static SM2CryptoHelper()
{
var curve = GMNamedCurves.GetByName("sm2p256v1");
DomainParams = new ECDomainParameters(curve.Curve, curve.G, curve.N, curve.H);
}
#region 生成密钥对
// 生成SM2密钥对
public static (byte[] privateKey, byte[] publicKey) GenerateKeyPair()
{
var gen = new ECKeyPairGenerator();
gen.Init(new ECKeyGenerationParameters(DomainParams, new SecureRandom()));
var keyPair = gen.GenerateKeyPair();
var privKey = (ECPrivateKeyParameters)keyPair.Private;
var pubKey = (ECPublicKeyParameters)keyPair.Public;
return (
AdjustTo32Bytes(privKey.D.ToByteArrayUnsigned()),
pubKey.Q.GetEncoded(false) // 未压缩格式公钥(65字节)
);
}
#endregion
#region 签名 验签
// SM2签名 (R|S裸编码64字节)
public static byte[] Sign(byte[] privateKey, byte[] data)
{
if (privateKey == null || privateKey.Length != 32)
throw new ArgumentException("Private key must be 32 bytes");
var d = new BigInteger(1, privateKey);
var privateKeyParam = new ECPrivateKeyParameters(d, DomainParams);
// 使用国标要求的用户ID
var signer = new SM2Signer(new SM3Digest());
signer.Init(true, new ParametersWithID(
new ParametersWithRandom(privateKeyParam, new SecureRandom()),
DefaultUserId));
signer.BlockUpdate(data, 0, data.Length);
byte[] derSignature = signer.GenerateSignature();
// 解析DER格式为R|S裸编码
//return DerToRawSignature(derSignature);
// 使用更可靠的 DER 转裸签名方法
return ConvertDerToRawSignature(derSignature, 32);
}
// SM2验签
public static bool Verify(byte[] publicKey, byte[] data, byte[] signature)
{
if (signature.Length != 64)
throw new ArgumentException("Signature must be 64 bytes raw format (R|S)");
if (publicKey == null || (publicKey.Length != 65 && publicKey[0] == 0x04))
throw new ArgumentException("Public key must be in uncompressed format (65 bytes)");
try
{
// 将裸签名转换为DER格式
//byte[] derSignature = RawToDerSignature(signature);
byte[] derSignature = ConvertRawToDerSignature(signature, 32);
ECPoint q = DomainParams.Curve.DecodePoint(publicKey);
var pubKey = new ECPublicKeyParameters(q, DomainParams);
var signer = new SM2Signer(new SM3Digest());
signer.Init(false, new ParametersWithID(pubKey, DefaultUserId));
signer.BlockUpdate(data, 0, data.Length);
return signer.VerifySignature(derSignature);
}
catch
{
return false;
}
}
#endregion
#region 加密解密
// SM2加密 (C1C3C2模式)
public static byte[] Encrypt(byte[] publicKey, byte[] plaintext)
{
if (publicKey == null || publicKey.Length != 65)
throw new ArgumentException("Public key must be 65 bytes uncompressed format");
ECPoint q = DomainParams.Curve.DecodePoint(publicKey);
var pubKey = new ECPublicKeyParameters(q, DomainParams);
var cipher = new SM2Engine(new SM3Digest());
cipher.Init(true, new ParametersWithRandom(pubKey, new SecureRandom()));
byte[] encrypted = cipher.ProcessBlock(plaintext, 0, plaintext.Length);
// 转换为C1C3C2模式
return ConvertToC1C3C2(encrypted);
//return cipher.ProcessBlock(plaintext, 0, plaintext.Length);
}
/// <summary>
/// 将C1C2C3格式转换为C1C3C2格式
/// </summary>
private static byte[] ConvertToC1C3C2(byte[] c1c2c3)
{
// 密文结构: C1(65字节) + C2(明文长度) + C3(32字节)
int c1Length = 65; // C1部分长度
int c3Length = 32; // C3部分长度
int c2Length = c1c2c3.Length - c1Length - c3Length; // C2部分长度
if (c2Length < 0)
throw new ArgumentException("Invalid ciphertext length");
// 创建新数组: C1(65) + C3(32) + C2(变长)
byte[] c1c3c2 = new byte[c1c2c3.Length];
// 复制C1部分 (0-65字节)
Buffer.BlockCopy(c1c2c3, 0, c1c3c2, 0, c1Length);
// 复制C3部分 (最后32字节)
Buffer.BlockCopy(c1c2c3, c1Length + c2Length, c1c3c2, c1Length, c3Length);
// 复制C2部分 (65到65+c2Length)
Buffer.BlockCopy(c1c2c3, c1Length, c1c3c2, c1Length + c3Length, c2Length);
return c1c3c2;
}
// SM2解密 (C1C3C2模式)
public static byte[] Decrypt(byte[] privateKey, byte[] ciphertext)
{
if (privateKey == null || privateKey.Length != 32)
throw new ArgumentException("Private key must be 32 bytes");
// 先将密文转换为C1C2C3模式BouncyCastle默认格式
byte[] c1c2c3 = ConvertToC1C2C3(ciphertext);
var d = new BigInteger(1, privateKey);
var privKey = new ECPrivateKeyParameters(d, DomainParams);
// 明确指定C1C3C2模式
var cipher = new SM2Engine(new SM3Digest());
cipher.Init(false, privKey);
try
{
return cipher.ProcessBlock(c1c2c3, 0, c1c2c3.Length);
//return cipher.ProcessBlock(ciphertext, 0, ciphertext.Length);
}
catch (Exception ex)
{
throw new CryptoException("Decryption failed", ex);
}
}
/// <summary>
/// 将C1C3C2格式转换为C1C2C3格式
/// </summary>
private static byte[] ConvertToC1C2C3(byte[] c1c3c2)
{
// 密文结构: C1(65字节) + C3(32字节) + C2(明文长度)
int c1Length = 65; // C1部分长度
int c3Length = 32; // C3部分长度
int c2Length = c1c3c2.Length - c1Length - c3Length; // C2部分长度
if (c2Length < 0)
throw new ArgumentException("Invalid ciphertext length");
// 创建新数组: C1(65) + C2(变长) + C3(32)
byte[] c1c2c3 = new byte[c1c3c2.Length];
// 复制C1部分 (0-65字节)
Buffer.BlockCopy(c1c3c2, 0, c1c2c3, 0, c1Length);
// 复制C2部分 (65+32到结束)
Buffer.BlockCopy(c1c3c2, c1Length + c3Length, c1c2c3, c1Length, c2Length);
// 复制C3部分 (65到65+32)
Buffer.BlockCopy(c1c3c2, c1Length, c1c2c3, c1Length + c2Length, c3Length);
return c1c2c3;
}
#endregion
#region 内部工具方法
private static byte[] AdjustTo32Bytes(byte[] input)
{
if (input.Length == 32) return input;
if (input.Length > 32)
throw new ArgumentException("Input too long for 32-byte adjustment");
byte[] output = new byte[32];
Buffer.BlockCopy(input, 0, output, 32 - input.Length, input.Length);
return output;
}
// === 新增方法:可靠的 DER 转裸签名 ===
private static byte[] ConvertDerToRawSignature(byte[] derSignature, int partLength)
{
Asn1Sequence seq = (Asn1Sequence)Asn1Object.FromByteArray(derSignature);
byte[] rBytes = PadLeadingZeros(((DerInteger)seq[0]).Value.ToByteArrayUnsigned(), partLength);
byte[] sBytes = PadLeadingZeros(((DerInteger)seq[1]).Value.ToByteArrayUnsigned(), partLength);
byte[] rawSig = new byte[partLength * 2];
Buffer.BlockCopy(rBytes, 0, rawSig, 0, partLength);
Buffer.BlockCopy(sBytes, 0, rawSig, partLength, partLength);
return rawSig;
}
// === 新增方法:安全的填充处理 ===
private static byte[] PadLeadingZeros(byte[] input, int requiredLength)
{
if (input.Length == requiredLength)
return input;
if (input.Length > requiredLength)
throw new InvalidOperationException("Input longer than required length");
byte[] padded = new byte[requiredLength];
int offset = requiredLength - input.Length;
Buffer.BlockCopy(input, 0, padded, offset, input.Length);
return padded;
}
// === 新增方法:可靠的裸签名转 DER ===
private static byte[] ConvertRawToDerSignature(byte[] rawSignature, int partLength)
{
if (rawSignature.Length != partLength * 2)
throw new ArgumentException("Invalid raw signature length");
byte[] rBytes = new byte[partLength];
byte[] sBytes = new byte[partLength];
Buffer.BlockCopy(rawSignature, 0, rBytes, 0, partLength);
Buffer.BlockCopy(rawSignature, partLength, sBytes, 0, partLength);
// 移除前导零(匹配 Java 行为)
BigInteger r = new BigInteger(1, rBytes);
BigInteger s = new BigInteger(1, sBytes);
Asn1EncodableVector v = new Asn1EncodableVector();
v.Add(new DerInteger(r));
v.Add(new DerInteger(s));
return new DerSequence(v).GetEncoded();
}
#endregion
}
}

@ -0,0 +1,195 @@
using Org.BouncyCastle.Crypto.Digests;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Modes;
using Org.BouncyCastle.Crypto.Paddings;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Security;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
namespace Infrastructure.Helpers
{
public class SM4CryptoHelper
{
const int SM4_KEY_SIZE = 128 / 8; // 16 bytes
const int BLOCK_SIZE = 16; // SM4 block size is 16 bytes
#region 随机密钥
/// <summary>
/// sm4 随机密钥
/// </summary>
/// <returns></returns>
public static byte[] GenerateSM4Key()
{
using (var rng = RandomNumberGenerator.Create())
{
byte[] key = new byte[SM4_KEY_SIZE];
rng.GetBytes(key);
return key;
}
}
#endregion
#region CBC模式PKCS7填充
// 生成随机IV
public static byte[] GenerateIV()
{
using (var rng = RandomNumberGenerator.Create())
{
byte[] iv = new byte[BLOCK_SIZE];
rng.GetBytes(iv);
return iv;
}
}
// SM4加密 (CBC模式PKCS7填充)
public static byte[] SM4Encrypt(byte[] key, byte[] iv, byte[] plaintext)
{
// 创建加密器
var engine = new SM4Engine();
var blockCipher = new CbcBlockCipher(engine);
var cipher = new PaddedBufferedBlockCipher(blockCipher, new Pkcs7Padding());
var keyParam = new KeyParameter(key);
var keyParamWithIv = new ParametersWithIV(keyParam, iv);
// 初始化加密器
cipher.Init(true, keyParamWithIv);
// 处理数据
byte[] output = new byte[cipher.GetOutputSize(plaintext.Length)];
int len = cipher.ProcessBytes(plaintext, 0, plaintext.Length, output, 0);
len += cipher.DoFinal(output, len);
// 返回正确长度的密文
if (len < output.Length)
{
byte[] result = new byte[len];
Array.Copy(output, 0, result, 0, len);
return result;
}
return output;
}
// SM4解密 (CBC模式PKCS7填充)
public static byte[] SM4Decrypt(byte[] key, byte[] iv, byte[] ciphertext)
{
// 创建解密器
var engine = new SM4Engine();
var blockCipher = new CbcBlockCipher(engine);
var cipher = new PaddedBufferedBlockCipher(blockCipher, new Pkcs7Padding());
var keyParam = new KeyParameter(key);
var keyParamWithIv = new ParametersWithIV(keyParam, iv);
// 初始化解密器
cipher.Init(false, keyParamWithIv);
// 处理数据
byte[] output = new byte[cipher.GetOutputSize(ciphertext.Length)];
int len = cipher.ProcessBytes(ciphertext, 0, ciphertext.Length, output, 0);
len += cipher.DoFinal(output, len);
// 返回正确长度的明文
if (len < output.Length)
{
byte[] result = new byte[len];
Array.Copy(output, 0, result, 0, len);
return result;
}
return output;
}
#endregion
#region ECB加密(PKCS#7填充)
// SM4 ECB加密(PKCS#7填充)
public static byte[] Encrypt(byte[] key, byte[] plaintext)
{
if (key == null || key.Length != BLOCK_SIZE)
throw new ArgumentException("Key must be 16 bytes (128 bits)");
// 创建加密器
var engine = new SM4Engine();
var cipher = new PaddedBufferedBlockCipher(engine, new Pkcs7Padding());
cipher.Init(true, new KeyParameter(key));
// 处理数据
byte[] output = new byte[cipher.GetOutputSize(plaintext.Length)];
int len = cipher.ProcessBytes(plaintext, 0, plaintext.Length, output, 0);
len += cipher.DoFinal(output, len);
// 返回正确长度的密文
if (len < output.Length)
{
byte[] result = new byte[len];
Buffer.BlockCopy(output, 0, result, 0, len);
return result;
}
return output;
}
// SM4 ECB解密(PKCS#7填充)
public static byte[] Decrypt(byte[] key, byte[] ciphertext)
{
if (key == null || key.Length != BLOCK_SIZE)
throw new ArgumentException("Key must be 16 bytes (128 bits)");
// 创建解密器
var engine = new SM4Engine();
var cipher = new PaddedBufferedBlockCipher(engine, new Pkcs7Padding());
cipher.Init(false, new KeyParameter(key));
// 处理数据
byte[] output = new byte[cipher.GetOutputSize(ciphertext.Length)];
int len = cipher.ProcessBytes(ciphertext, 0, ciphertext.Length, output, 0);
len += cipher.DoFinal(output, len);
// 返回正确长度的明文
if (len < output.Length)
{
byte[] result = new byte[len];
Buffer.BlockCopy(output, 0, result, 0, len);
return result;
}
return output;
}
#endregion
//// SM2加密
//public static byte[] SM2Encrypt(byte[] publicKey, byte[] data)
//{
// var curve = Org.BouncyCastle.Asn1.GM.GMNamedCurves.GetByName("sm2p256v1");
// var domainParams = new ECDomainParameters(curve.Curve, curve.G, curve.N, curve.H);
// var q = curve.Curve.DecodePoint(publicKey);
// var pubKey = new ECPublicKeyParameters(q, domainParams);
// var cipher = new SM2Engine(new SM3Digest());
// cipher.Init(true, new ParametersWithRandom(pubKey, new SecureRandom()));
// return cipher.ProcessBlock(data, 0, data.Length);
//}
//// SM2解密
//public static byte[] SM2Decrypt(byte[] privateKey, byte[] encryptedData)
//{
// var curve = Org.BouncyCastle.Asn1.GM.GMNamedCurves.GetByName("sm2p256v1");
// var domainParams = new ECDomainParameters(curve.Curve, curve.G, curve.N, curve.H);
// var d = new BigInteger(1, privateKey);
// var privKey = new ECPrivateKeyParameters(d, domainParams);
// var cipher = new SM2Engine(new SM3Digest());
// cipher.Init(false, privKey);
// return cipher.ProcessBlock(encryptedData, 0, encryptedData.Length);
//}
}
}

@ -0,0 +1,97 @@
using System;
using System.Text;
using Org.BouncyCastle.Asn1.X9;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Crypto.Signers;
public class TokenGenerator
{
// 1. 获取当前时间的毫秒级时间戳 A
public static long GetCurrentTimestamp()
{
return DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
}
// 2. 拼接 B + A 得到 C
public static string ConcatenateCodeAndTimestamp(string codeB, long timestampA)
{
return $"{codeB}{timestampA}";
}
// 3. 获取 C 的 UTF-8 字节数组 D
public static byte[] GetUtf8Bytes(string input)
{
return Encoding.UTF8.GetBytes(input);
}
// 4. 将 Hex 或 Base64 字符串私钥转换为 ECPrivateKeyParameters
public static ECPrivateKeyParameters ParsePrivateKey(string privateKeyStr)
{
// 假设私钥是 Hex 字符串(如 "ABCD1234..."
byte[] privateKeyBytes = HexToBytes(privateKeyStr); // 如果是 Base64用 Convert.FromBase64String
// SM2 曲线参数
var curve = ECNamedCurveTable.GetByName("sm2p256v1");
var domainParams = new ECDomainParameters(curve.Curve, curve.G, curve.N, curve.H);
// 创建私钥
var privateKey = new ECPrivateKeyParameters(new BigInteger(1, privateKeyBytes), domainParams);
return privateKey;
}
// 5. 使用 SM2 私钥签名 D 得到 E
public static byte[] SignWithSm2(byte[] data, ECPrivateKeyParameters privateKey)
{
var signer = new SM2Signer();
signer.Init(true, privateKey);
signer.BlockUpdate(data, 0, data.Length);
return signer.GenerateSignature();
}
// 6. 对 E 进行 Base64 编码得到 F
public static string Base64Encode(byte[] data)
{
return Convert.ToBase64String(data);
}
// 7. 组装 Token: {B}.{A}.{F}
public static string GenerateToken(string codeB, string privateKeyStr)
{
// 1. 获取时间戳 A
long timestampA = GetCurrentTimestamp();
// 2. 拼接 B + A 得到 C
string c = ConcatenateCodeAndTimestamp(codeB, timestampA);
// 3. 获取 UTF-8 字节数组 D
byte[] d = GetUtf8Bytes(c);
// 4. 解析私钥字符串
ECPrivateKeyParameters privateKey = ParsePrivateKey(privateKeyStr);
// 5. SM2 签名得到 E
byte[] e = SignWithSm2(d, privateKey);
// 6. Base64 编码得到 F
string f = Base64Encode(e);
// 7. 组装 Token
return $"{codeB}.{timestampA}.{f}";
}
// 辅助方法Hex 字符串转字节数组
private static byte[] HexToBytes(string hex)
{
if (hex.Length % 2 != 0)
throw new ArgumentException("Hex 字符串长度必须是偶数");
byte[] bytes = new byte[hex.Length / 2];
for (int i = 0; i < bytes.Length; i++)
{
bytes[i] = Convert.ToByte(hex.Substring(i * 2, 2), 16);
}
return bytes;
}
}

@ -8,6 +8,7 @@ using Infrastructure.Extensions.AutofacManager;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyModel;
using OpenAuth.App.Interface;
using OpenAuth.App.ServiceApp;
using OpenAuth.App.SSO;
using OpenAuth.Repository;
using SqlSugar;
@ -29,6 +30,7 @@ namespace OpenAuth.App
//注册app层
builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly()).InstancePerLifetimeScope();
//builder.RegisterType(typeof(TestApp)).InstancePerLifetimeScope();
builder.RegisterType(typeof(RedisCacheContext)).As(typeof(ICacheContext)).InstancePerLifetimeScope();
//builder.RegisterType(typeof(CacheContext)).As(typeof(ICacheContext));

@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OpenAuth.App.ServiceApp.Response
{
public class ReciveData<T>
{
public int code { get; set; }
public string message { get; set; }
public T data { get; set; }
public string traceid { get; set; }
}
}

@ -0,0 +1,132 @@
using OpenAuth.App.BaseApp.Base;
using OpenAuth.Repository.Domain;
using OpenAuth.Repository;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Infrastructure.CloudSdk.minio;
using OpenAuth.App.BasicQueryService;
using OpenAuth.App.Interface;
using OpenAuth.WebApi;
using SqlSugar;
using Infrastructure;
using System.Security.Cryptography.X509Certificates;
using Infrastructure.Helpers;
using System.Text.Json;
using NetModular.DocX.Core;
using System.DirectoryServices.Protocols;
using OpenAuth.App.ServiceApp.Response;
using Microsoft.AspNetCore.DataProtection;
namespace OpenAuth.App.ServiceApp
{
public class TestApp : SqlSugarBaseApp<LasaDronePort, SugarDbContext>
{
private EncryptionHelper _helper;
public TestApp(EncryptionHelper helper, ISugarUnitOfWork<SugarDbContext> unitWork, ISimpleClient<LasaDronePort> repository, IAuth auth): base(unitWork, repository, auth)
{
_helper = helper;
}
public async Task<Response<string>> RegistService()
{
//using var httpClient = new HttpClient();
Response<string> Response=new Response<string>();
var handler = new HttpClientHandler();
//handler.ClientCertificates.Add(cert);
// 如果需要忽略服务器证书错误(仅测试环境)
handler.ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) => true;
using (var client = new HttpClient())
{
try
{
string url = "https://wp.tianmu.cloud:5443/zhcfzx/droneAirport/RegistService";
// var param = new Dictionary<string, string>()
//{
// { "serviceUrl", "https://xxx.com/mdc/v1/" },
// { "1iveStreampluginUrl", "https://ss.com/drone/v1/livestream.js" },
// { "contacts", "孟三" },
// { "phone", "18390849120" },
//};
string json= "{" +
"\"serviceUrl\": \"https://xxx.com/mdc/v1/\"," +
"\"liveStreampluginUrl\": \"https://xxx.com/drone/v1/livestream.js\"," +
"\"contacts\": \"孟三\"," +
"\"phone\": \"18390849120\"" +
"}";
string x_lc_secret = _helper.getxseret();
string centercode = "UAV32_LJY2FPMYDE6UDES3P3ZD7V3IKQ";
string x_token = _helper.GetToken(centercode);
// 序列化为 JSON 字符串
//string json = JsonSerializer.Serialize(param);
// 转换为字节数组
byte[] bytes = Encoding.UTF8.GetBytes(json);
var encryptedData = _helper.Encrypt(bytes);
// 创建请求体
var httpContent = new StringContent(encryptedData, Encoding.UTF8, "application/json");
// 添加请求头
client.DefaultRequestHeaders.Add("x-lc-secret", x_lc_secret);
client.DefaultRequestHeaders.Add("x-lc-token", x_token);
//发送请求
HttpResponseMessage response = await client.PostAsync(url, httpContent);
response.EnsureSuccessStatusCode();
// 获取响应头中的 x_cl_screte 参数
string resx_cl_screte = GetHeaderValue(response, "x-lc-secret");
// 读取响应内容并反序列化
string responseBody = await response.Content.ReadAsStringAsync();
var result = JsonSerializer.Deserialize<ReciveData<string>>(responseBody);
//解密数据
byte[] resbytesx = Convert.FromBase64String(resx_cl_screte);
byte[] resdatabytes = Convert.FromBase64String(result?.data);
string data = _helper.Decrypt(resbytesx, resdatabytes);
Response.Result = data;
Response.Message = result.message;
Response.Result = result.code.ToString();
}
catch (HttpRequestException e)
{
Console.WriteLine("\nException Caught!");
Console.WriteLine("Message :{0} ", e.Message);
Response.Result = "连接错误";
}
}
return Response;
}
// 安全获取响应头值的方法
private static string GetHeaderValue(HttpResponseMessage response, string headerName)
{
if (response.Headers.TryGetValues(headerName, out IEnumerable<string> values))
{
return string.Join(", ", values); // 如果多个值则合并
}
// 尝试忽略大小写再次查找
foreach (var header in response.Headers)
{
if (header.Key.Equals(headerName, StringComparison.OrdinalIgnoreCase))
{
return string.Join(", ", header.Value);
}
}
return null; // 未找到
}
}
}

@ -0,0 +1,44 @@
using Infrastructure;
using Infrastructure.Cache;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using OpenAuth.App.ServiceApp;
namespace OpenAuth.WebApi.Controllers.ServiceControllers
{
/// <summary>
/// 对接
/// </summary>
[Route("api/[controller]/[action]")]
[ApiController]
public class TestController: ControllerBase
{
private readonly TestApp _app;
public TestController(TestApp app)
{
_app = app;
}
/// <summary>
/// 测试接口
/// </summary>
/// <returns></returns>
[HttpPost]
[AllowAnonymous]
public async Task<Response<string>> RegistService()
{
var result = new Response<string>();
try
{
result = await _app.RegistService();
}
catch (Exception ex)
{
result.Code = 500;
result.Message = ex.Message;
}
return result;
}
}
}

@ -8,6 +8,7 @@ using Infrastructure.Cache;
using Infrastructure.CloudSdk.minio;
using Infrastructure.CloudSdk.mqttmessagecenter;
using Infrastructure.Extensions.AutofacManager;
using Infrastructure.Helpers;
using Infrastructure.Middleware;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.Http.Features;
@ -21,6 +22,7 @@ using Npgsql;
using OpenAuth.App;
using OpenAuth.App.BaseApp.ImMsgManager;
using OpenAuth.App.HostedService;
using OpenAuth.App.ServiceApp;
using OpenAuth.Repository;
using OpenAuth.WebApi.Model;
using OpenAuth.WebApi.Model.mqtt;
@ -48,6 +50,7 @@ namespace OpenAuth.WebApi
{
services.AddHttpContextAccessor();
services.AddSingleton<MqttClientManager>();
services.AddSingleton<EncryptionHelper>();
// minio client
services.AddSingleton(_ => new MinioService());

Loading…
Cancel
Save