赞
踩
本文主要介绍以非对称加密+对称加密结合的方式对post请求的接口数据进行加密。
实现思路
一.前端加密
- let data = parameter.data;
- let suijiNum = randomNumber();
- data = JSON.stringify(data);
- console.log("原始数据:" + data);
- data = encrypt(data, suijiNum);//非对称方式加密数据体
- data = Qs.stringify({data});
- axios.post(parameter.url, data, { headers: { 'token': encrypt(getToken(), suijiNum), "aeskey": rsaEncryp(suijiNum) } })
- .then(res => {
- if (res.data.statusCode != 200) {
- if (res.data.statusCode == 401) {
- Message({
- message: '登录信息已过期,请重新登录',
- type: 'error',
- duration: 5 * 1000
- });
- setTimeout(_ => {
- store.dispatch('LogOut').then(() => {
- location.reload() // 为了重新实例化vue- router对象避免bug
- })
- }, 3000)
- } else {
- Message({
- message: res.data.msg,
- type: 'error',
- duration: 5 * 1000
- });
- }
- } else {
- parameter.fun(res);
- }
- })
- .catch(err => {
- console.log(err);
- Message({
- message: err.message,
- type: 'error',
- duration: 5 * 1000
- });
- });
- }
-
- function rsaEncryp(data) {
- let encryption = new JSEncrypt()
- encryption.setPublicKey('MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoQh0wEqx/R2H1v00IU12Oc30fosRC/frhH89L6G+fzeaqI19MYQhEPMU13wpeqRONCUta+2iC1sgCNQ9qGGf19yGdZUfueaB1Nu9rdueQKXgVurGHJ+5N71UFm+OP1XcnFUCK4wT5d7ZIifXxuqLehP9Ts6sNjhVfa+yU+VjF5HoIe69OJEPo7OxRZcRTe17khc93Ic+PfyqswQJJlY/bgpcLJQnM+QuHmxNtF7/FpAx9YEQsShsGpVo7JaKgLo+s6AFoJ4QldQKir2vbN9vcKRbG3piElPilWDpjXQkOJZhUloh/jd7QrKFimZFldJ1r6Q59QYUyGKZARUe0KZpMQIDAQAB')
- let newData = encryption.encrypt(data)
- return newData
- }
-
- function randomNumber() {
- return (('0000000000000000' + Math.floor(Math.random() * 9999999999999999)).slice(-16));
- }
二.后台解密
(1).后台在过滤器中对数据进行解密操作,创建过滤器DataDecryptFilter。
首先用私钥解密对称加密的密钥aeskey,然后再用aeskey去解密数据体
- /// <summary>
- /// 数据解密过滤器
- /// 前端只对post请求接口进行加密(先用非对称加密方式(RSA)加密对称加密的密钥,然后对称加密(AES)数据包)
- /// create by LiuCheng 2019.5.29
- /// </summary>
- public class DataDecryptFilter : ActionFilterAttribute
- {
- public override async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
- {
- var noEncrypt = ConfigHelper.GetSectionValue("NoEncrypt");//白名单
- var method = context.HttpContext.Request.Method;
- if (method == "POST" && !noEncrypt.Contains(context.HttpContext.Request.Path))
- {
- string aeskey = context.HttpContext.Request.Headers["aeskey"];
- if (aeskey.Length > 36)//判断aeskey是否已经解密,若未解密则先进行解密操作
- {
- var rsaHelper = new RSAHelper(RSAType.RSA2, Encoding.UTF8);
- aeskey = rsaHelper.Decrypt(aeskey);
- }
- //解密数据包
- var data = context.HttpContext.Request.Form.FirstOrDefault().Value;
- var dataJson = AESHelper.AesDecrypt(data, aeskey);
-
- if (string.IsNullOrWhiteSpace(dataJson))
- {
- context.Result = AjaxHelper.JsonResult(HttpStatusCode.BadRequest, " 数据请求不合法!");
- return;
- }
- if (context.ActionArguments.Values.Count > 0)
- {
- //-----------model接收模式----------//
- var type = context.ActionArguments.Values.ToList()[0].GetType();
-
- PropertyInfo[] ps = type.GetProperties();
-
- var model = context.ActionArguments.Values.ToList()[0];
-
- var dy = JsonConvert.DeserializeObject(dataJson, type);
-
- var type2 = dy.GetType();
- PropertyInfo[] ps2 = type2.GetProperties();
-
- foreach (PropertyInfo i in ps)
- {
- foreach (PropertyInfo i2 in ps2)
- {
- var value = i2.GetValue(dy, null);
- if (i.Name == i2.Name && value != null)
- {
- i.SetValue(model, value, null);
- }
- }
- }
- }
- else
- {
- //-----------变量接收模式----------//
- var dy = (JObject)JsonConvert.DeserializeObject(dataJson);
- var parameterslist = context.ActionDescriptor.Parameters.ToList();
- foreach (var item in parameterslist)
- {
- if (dy[item.Name] == null)
- continue;
- var vaule = ConvertObject(dy[item.Name].ToString(), item.ParameterType);
- context.ActionArguments.Add(item.Name, vaule);
- }
- }
- }
- await base.OnActionExecutionAsync(context, next);
- }
-
-
- /// <summary>
- /// 将一个对象转换为指定类型
- /// </summary>
- /// <param name="obj">待转换的对象</param>
- /// <param name="type">目标类型</param>
- /// <returns>转换后的对象</returns>
- private object ConvertObject(object obj, Type type)
- {
- if (type == null) return obj;
- if (obj == null) return type.IsValueType ? Activator.CreateInstance(type) : null;
-
- Type underlyingType = Nullable.GetUnderlyingType(type);
- if (type.IsAssignableFrom(obj.GetType())) // 如果待转换对象的类型与目标类型兼容,则无需转换
- {
- return obj;
- }
- else if ((underlyingType ?? type).IsEnum) // 如果待转换的对象的基类型为枚举
- {
- if (underlyingType != null && string.IsNullOrEmpty(obj.ToString())) // 如果目标类型为可空枚举,并且待转换对象为null 则直接返回null值
- {
- return null;
- }
- else
- {
- return Enum.Parse(underlyingType ?? type, obj.ToString());
- }
- }
- else if (typeof(IConvertible).IsAssignableFrom(underlyingType ?? type)) // 如果目标类型的基类型实现了IConvertible,则直接转换
- {
- try
- {
- return Convert.ChangeType(obj, underlyingType ?? type, null);
- }
- catch
- {
- return underlyingType == null ? Activator.CreateInstance(type) : null;
- }
- }
- else
- {
- TypeConverter converter = TypeDescriptor.GetConverter(type);
- if (converter.CanConvertFrom(obj.GetType()))
- {
- return converter.ConvertFrom(obj);
- }
- ConstructorInfo constructor = type.GetConstructor(Type.EmptyTypes);
- if (constructor != null)
- {
- object o = constructor.Invoke(null);
- PropertyInfo[] propertys = type.GetProperties();
- Type oldType = obj.GetType();
- foreach (PropertyInfo property in propertys)
- {
- PropertyInfo p = oldType.GetProperty(property.Name);
- if (property.CanWrite && p != null && p.CanRead)
- {
- property.SetValue(o, ConvertObject(p.GetValue(obj, null), property.PropertyType), null);
- }
- }
- return o;
- }
- }
- return obj;
- }
- }
(2).对称加密工具类
- /// <summary>
- /// 对称加密
- /// </summary>
- public class AESHelper
- {
- /// <summary>
- /// AES加密
- /// </summary>
- /// <param name="str"></param>
- /// <param name="key"></param>
- /// <returns></returns>
- public static string AesEncrypt(string str, string key)
- {
- string result;
- try
- {
- if (string.IsNullOrEmpty(str))
- {
- result = null;
- }
- else
- {
- byte[] bytes = Encoding.UTF8.GetBytes(str);
- RijndaelManaged rijndaelManaged = new RijndaelManaged
- {
- Key = Encoding.UTF8.GetBytes(key),
- Mode = CipherMode.ECB,
- Padding = PaddingMode.PKCS7
- };
- ICryptoTransform cryptoTransform = rijndaelManaged.CreateEncryptor();
- byte[] array = cryptoTransform.TransformFinalBlock(bytes, 0, bytes.Length);
- result = Convert.ToBase64String(array, 0, array.Length);
-
- return result;
- }
- }
- catch (Exception ex)
- {
- result = null;
- System.Console.WriteLine(ex);
- }
- return result;
- }
-
- /// <summary>
- /// AES解密
- /// </summary>
- /// <param name="str"></param>
- /// <param name="key"></param>
- /// <returns></returns>
- public static string AesDecrypt(string str, string key)
- {
- if (string.IsNullOrEmpty(str))
- {
- return null;
- }
- string result;
- try
- {
- byte[] array = Convert.FromBase64String(str);
-
- RijndaelManaged rijndaelManaged = new RijndaelManaged
- {
- Key = Encoding.UTF8.GetBytes(key),
- Mode = CipherMode.ECB,
- Padding = PaddingMode.PKCS7
- };
- ICryptoTransform cryptoTransform = rijndaelManaged.CreateDecryptor();
- byte[] bytes = cryptoTransform.TransformFinalBlock(array, 0, array.Length);
- result = Encoding.UTF8.GetString(bytes);
- }
- catch (Exception ex)
- {
- result = null;
- Console.WriteLine(ex);
- }
- return result;
- }
- }
(3).非对称加密工具类
- /// <summary>
- /// 非对称加密
- /// </summary>
- public class RSAHelper
- {
- private readonly RSA _privateKeyRsaProvider;
- private readonly RSA _publicKeyRsaProvider;
- private readonly HashAlgorithmName _hashAlgorithmName;
- private readonly Encoding _encoding;
- private readonly string privateKey = ConfigHelper.GetSectionValue("privateKey");
- private readonly string publicKey = ConfigHelper.GetSectionValue("publicKey");
-
- /// <summary>
- /// 实例化RSAHelper
- /// </summary>
- /// <param name="rsaType">加密算法类型 RSA SHA1;RSA2 SHA256 密钥长度至少为2048</param>
- /// <param name="encoding">编码类型</param>
- public RSAHelper(RSAType rsaType, Encoding encoding)
- {
- _encoding = encoding;
- if (!string.IsNullOrEmpty(privateKey))
- {
- _privateKeyRsaProvider = CreateRsaProviderFromPrivateKey(privateKey);
- }
-
- if (!string.IsNullOrEmpty(publicKey))
- {
- _publicKeyRsaProvider = CreateRsaProviderFromPublicKey(publicKey);
- }
-
- _hashAlgorithmName = rsaType == RSAType.RSA ? HashAlgorithmName.SHA1 : HashAlgorithmName.SHA256;
- }
-
- #region 使用私钥签名
-
- /// <summary>
- /// 使用私钥签名
- /// </summary>
- /// <param name="data">原始数据</param>
- /// <returns></returns>
- public string Sign(string data)
- {
- byte[] dataBytes = _encoding.GetBytes(data);
-
- var signatureBytes = _privateKeyRsaProvider.SignData(dataBytes, _hashAlgorithmName, RSASignaturePadding.Pkcs1);
-
- return Convert.ToBase64String(signatureBytes);
- }
-
- #endregion
-
- #region 使用公钥验证签名
-
- /// <summary>
- /// 使用公钥验证签名
- /// </summary>
- /// <param name="data">原始数据</param>
- /// <param name="sign">签名</param>
- /// <returns></returns>
- public bool Verify(string data, string sign)
- {
- byte[] dataBytes = _encoding.GetBytes(data);
- byte[] signBytes = Convert.FromBase64String(sign);
-
- var verify = _publicKeyRsaProvider.VerifyData(dataBytes, signBytes, _hashAlgorithmName, RSASignaturePadding.Pkcs1);
-
- return verify;
- }
-
- #endregion
-
- #region 解密
-
- public string Decrypt(string cipherText)
- {
- if (_privateKeyRsaProvider == null)
- {
- throw new Exception("_privateKeyRsaProvider is null");
- }
- return Encoding.UTF8.GetString(_privateKeyRsaProvider.Decrypt(Convert.FromBase64String(cipherText), RSAEncryptionPadding.Pkcs1));
- }
-
- #endregion
-
- #region 加密
-
- public string Encrypt(string text)
- {
- if (_publicKeyRsaProvider == null)
- {
- throw new Exception("_publicKeyRsaProvider is null");
- }
- return Convert.ToBase64String(_publicKeyRsaProvider.Encrypt(Encoding.UTF8.GetBytes(text), RSAEncryptionPadding.Pkcs1));
- }
-
- #endregion
-
- #region 使用私钥创建RSA实例
-
- public RSA CreateRsaProviderFromPrivateKey(string privateKey)
- {
- var privateKeyBits = Convert.FromBase64String(privateKey);
-
- var rsa = RSA.Create();
- var rsaParameters = new RSAParameters();
-
- using (BinaryReader binr = new BinaryReader(new MemoryStream(privateKeyBits)))
- {
- byte bt = 0;
- ushort twobytes = 0;
- twobytes = binr.ReadUInt16();
- if (twobytes == 0x8130)
- binr.ReadByte();
- else if (twobytes == 0x8230)
- binr.ReadInt16();
- else
- throw new Exception("Unexpected value read binr.ReadUInt16()");
-
- twobytes = binr.ReadUInt16();
- if (twobytes != 0x0102)
- throw new Exception("Unexpected version");
-
- bt = binr.ReadByte();
- if (bt != 0x00)
- throw new Exception("Unexpected value read binr.ReadByte()");
-
- rsaParameters.Modulus = binr.ReadBytes(GetIntegerSize(binr));
- rsaParameters.Exponent = binr.ReadBytes(GetIntegerSize(binr));
- rsaParameters.D = binr.ReadBytes(GetIntegerSize(binr));
- rsaParameters.P = binr.ReadBytes(GetIntegerSize(binr));
- rsaParameters.Q = binr.ReadBytes(GetIntegerSize(binr));
- rsaParameters.DP = binr.ReadBytes(GetIntegerSize(binr));
- rsaParameters.DQ = binr.ReadBytes(GetIntegerSize(binr));
- rsaParameters.InverseQ = binr.ReadBytes(GetIntegerSize(binr));
- }
-
- rsa.ImportParameters(rsaParameters);
- return rsa;
- }
-
- #endregion
-
- #region 使用公钥创建RSA实例
-
- public RSA CreateRsaProviderFromPublicKey(string publicKeyString)
- {
- // encoded OID sequence for PKCS #1 rsaEncryption szOID_RSA_RSA = "1.2.840.113549.1.1.1"
- byte[] seqOid = { 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00 };
- byte[] seq = new byte[15];
-
- var x509Key = Convert.FromBase64String(publicKeyString);
-
- // --------- Set up stream to read the asn.1 encoded SubjectPublicKeyInfo blob ------
- using (MemoryStream mem = new MemoryStream(x509Key))
- {
- using (BinaryReader binr = new BinaryReader(mem)) //wrap Memory Stream with BinaryReader for easy reading
- {
- byte bt = 0;
- ushort twobytes = 0;
-
- twobytes = binr.ReadUInt16();
- if (twobytes == 0x8130) //data read as little endian order (actual data order for Sequence is 30 81)
- binr.ReadByte(); //advance 1 byte
- else if (twobytes == 0x8230)
- binr.ReadInt16(); //advance 2 bytes
- else
- return null;
-
- seq = binr.ReadBytes(15); //read the Sequence OID
- if (!CompareBytearrays(seq, seqOid)) //make sure Sequence for OID is correct
- return null;
-
- twobytes = binr.ReadUInt16();
- if (twobytes == 0x8103) //data read as little endian order (actual data order for Bit String is 03 81)
- binr.ReadByte(); //advance 1 byte
- else if (twobytes == 0x8203)
- binr.ReadInt16(); //advance 2 bytes
- else
- return null;
-
- bt = binr.ReadByte();
- if (bt != 0x00) //expect null byte next
- return null;
-
- twobytes = binr.ReadUInt16();
- if (twobytes == 0x8130) //data read as little endian order (actual data order for Sequence is 30 81)
- binr.ReadByte(); //advance 1 byte
- else if (twobytes == 0x8230)
- binr.ReadInt16(); //advance 2 bytes
- else
- return null;
-
- twobytes = binr.ReadUInt16();
- byte lowbyte = 0x00;
- byte highbyte = 0x00;
-
- if (twobytes == 0x8102) //data read as little endian order (actual data order for Integer is 02 81)
- lowbyte = binr.ReadByte(); // read next bytes which is bytes in modulus
- else if (twobytes == 0x8202)
- {
- highbyte = binr.ReadByte(); //advance 2 bytes
- lowbyte = binr.ReadByte();
- }
- else
- return null;
- byte[] modint = { lowbyte, highbyte, 0x00, 0x00 }; //reverse byte order since asn.1 key uses big endian order
- int modsize = BitConverter.ToInt32(modint, 0);
-
- int firstbyte = binr.PeekChar();
- if (firstbyte == 0x00)
- { //if first byte (highest order) of modulus is zero, don't include it
- binr.ReadByte(); //skip this null byte
- modsize -= 1; //reduce modulus buffer size by 1
- }
- byte[] modulus = binr.ReadBytes(modsize); //read the modulus bytes
- if (binr.ReadByte() != 0x02) //expect an Integer for the exponent data
- return null;
- int expbytes = (int)binr.ReadByte(); // should only need one byte for actual exponent data (for all useful values)
- byte[] exponent = binr.ReadBytes(expbytes);
- // ------- create RSACryptoServiceProvider instance and initialize with public key -----
- var rsa = RSA.Create();
- RSAParameters rsaKeyInfo = new RSAParameters
- {
- Modulus = modulus,
- Exponent = exponent
- };
- rsa.ImportParameters(rsaKeyInfo);
- return rsa;
- }
- }
- }
- #endregion
- #region 导入密钥算法
- private int GetIntegerSize(BinaryReader binr)
- {
- byte bt = 0;
- int count = 0;
- bt = binr.ReadByte();
- if (bt != 0x02)
- return 0;
- bt = binr.ReadByte();
- if (bt == 0x81)
- count = binr.ReadByte();
- else
- if (bt == 0x82)
- {
- var highbyte = binr.ReadByte();
- var lowbyte = binr.ReadByte();
- byte[] modint = { lowbyte, highbyte, 0x00, 0x00 };
- count = BitConverter.ToInt32(modint, 0);
- }
- else
- {
- count = bt;
- }
- while (binr.ReadByte() == 0x00)
- {
- count -= 1;
- }
- binr.BaseStream.Seek(-1, SeekOrigin.Current);
- return count;
- }
- private bool CompareBytearrays(byte[] a, byte[] b)
- {
- if (a.Length != b.Length)
- return false;
- int i = 0;
- foreach (byte c in a)
- {
- if (c != b[i])
- return false;
- i++;
- }
- return true;
- }
- #endregion
- }
- /// <summary>
- /// RSA算法类型
- /// </summary>
- public enum RSAType
- {
- /// <summary>
- /// SHA1
- /// </summary>
- RSA = 0,
- /// <summary>
- /// RSA2 密钥长度至少为2048
- /// SHA256
- /// </summary>
- RSA2
- }
(4).appsettings.json配置密钥
- "publicKey": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoQh0wEqx/R2H1v00IU12Oc30fosRC/frhH89L6G+fzeaqI19MYQhEPMU13wpeqRONCUta+2iC1sgCNQ9qGGf19yGdZUfueaB1Nu9rdueQKXgVurGHJ+5N71UFm+OP1XcnFUCK4wT5d7ZIifXxuqLehP9Ts6sNjhVfa+yU+VjF5HoIe69OJEPo7OxRZcRTe17khc93Ic+PfyqswQJJlY/bgpcLJQnM+QuHmxNtF7/FpAx9YEQsShsGpVo7JaKgLo+s6AFoJ4QldQKir2vbN9vcKRbG3piElPilWDpjXQkOJZhUloh/jd7QrKFimZFldJ1r6Q59QYUyGKZARUe0KZpMQIDAQAB",
- "privateKey": "MIIEpAIBAAKCAQEAoQh0wEqx/R2H1v00IU12Oc30fosRC/frhH89L6G+fzeaqI19MYQhEPMU13wpeqRONCUta+2iC1sgCNQ9qGGf19yGdZUfueaB1Nu9rdueQKXgVurGHJ+5N71UFm+OP1XcnFUCK4wT5d7ZIifXxuqLehP9Ts6sNjhVfa+yU+VjF5HoIe69OJEPo7OxRZcRTe17khc93Ic+PfyqswQJJlY/bgpcLJQnM+QuHmxNtF7/FpAx9YEQsShsGpVo7JaKgLo+s6AFoJ4QldQKir2vbN9vcKRbG3piElPilWDpjXQkOJZhUloh/jd7QrKFimZFldJ1r6Q59QYUyGKZARUe0KZpMQIDAQABAoIBAQCRZLUlOUvjIVqYvhznRK1OG6p45s8JY1r+UnPIId2Bt46oSLeUkZvZVeCnfq9k0Bzb8AVGwVPhtPEDh73z3dEYcT/lwjLXAkyPB6gG5ZfI/vvC/k7JYV01+neFmktw2/FIJWjEMMF2dvLNZ/Pm4bX1Dz9SfD/45Hwr8wqrvRzvFZsj5qqOxv9RPAudOYwCwZskKp/GF+L+3Ycod1Wu98imzMZUH+L5dQuDGg3kvf3ljIAegTPoqYBg0imNPYY/EGoFKnbxlK5S5/5uAFb16dGJqAz3XQCz9Is/IWrOTu0etteqV2Ncs8uqPdjed+b0j8CMsr4U1xjwPQ8WwdaJtTkRAoGBANAndgiGZkCVcc9975/AYdgFp35W6D+hGQAZlL6DmnucUFdXbWa/x2rTSEXlkvgk9X/PxOptUYsLJkzysTgfDywZwuIXLm9B3oNmv3bVgPXsgDsvDfaHYCgz0nHK6NSrX2AeX3yO/dFuoZsuk+J+UyRigMqYj0wjmxUlqj183hinAoGBAMYMOBgF77OXRII7GAuEut/nBeh2sBrgyzR7FmJMs5kvRh6Ck8wp3ysgMvX4lxh1ep8iCw1R2cguqNATr1klOdsCTOE9RrhuvOp3JrYzuIAK6MpH/uBICy4w1rW2+gQySsHcH40r+tNaTFQ7dQ1tef//iy/IW8v8i0t+csztE1JnAoGABdtWYt8FOYP688+jUmdjWWSvVcq0NjYeMfaGTOX/DsNTL2HyXhW/Uq4nNnBDNmAz2CjMbZwt0y+5ICkj+2REVQVUinAEinTcAe5+LKXNPx4sbX3hcrJUbk0m+rSu4G0B/f5cyXBsi9wFCAzDdHgBduCepxSr04Sc9Hde1uQQi7kCgYB0U20HP0Vh+TG2RLuE2HtjVDD2L/CUeQEiXEHzjxXWnhvTg+MIAnggvpLwQwmMxkQ2ACr5sd/3YuCpB0bxV5o594nsqq9FWVYBaecFEjAGlWHSnqMoXWijwu/6X/VOTbP3VjH6G6ECT4GR4DKKpokIQrMgZ9DzaezvdOA9WesFdQKBgQCWfeOQTitRJ0NZACFUn3Fs3Rvgc9eN9YSWj4RtqkmGPMPvguWo+SKhlk3IbYjrRBc5WVOdoX8JXb2/+nAGhPCuUZckWVmZe5pMSr4EkNQdYeY8kOXGSjoTOUH34ZdKeS+e399BkBWIiXUejX/Srln0H4KoHnTWgxwNpTsBCgXu8Q==",
三.Startup配置
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。