API 传输数据加密
//添加自定义消息处理
config.MessageHandlers.Add(new EncryptMessageHandler());
API
public class EncryptMessageHandler : MessageProcessingHandler { log4net.ILog logger = log4net.LogManager.GetLogger("EncryptionLogger"); protected override HttpRequestMessage ProcessRequest(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) { if (request.Content.IsMimeMultipartContent()) { return request; } string[] timeStampStrings = HttpContext.Current.Request.Headers.GetValues("timeStamp"); string[] accessKeyStrings = HttpContext.Current.Request.Headers.GetValues("accessKey"); string[] isEncrypt = HttpContext.Current.Request.Headers.GetValues("isEncrypt"); if (isEncrypt == null||isEncrypt.Length==0 || string.IsNullOrWhiteSpace(isEncrypt[0]) || isEncrypt[0] == 0.ToString()) { if (!(request.RequestUri.PathAndQuery + "").ToLower().Contains("api/file") && !(request.RequestUri.PathAndQuery + "").ToLower().Contains("api/phone") && !(request.RequestUri.PathAndQuery + "").ToLower().Contains("api/android/displaydata") && !(request.RequestUri.PathAndQuery + "").ToLower().Contains("api/login/getminversion")) { logger.Debug(string.Format("未加密请求:{0},请求IP:{1}",request.RequestUri.PathAndQuery,GetIP())); } return request; } if (timeStampStrings == null || timeStampStrings.Length < 1) { throw new UnauthorizedAccessException("请求的资源没有权限,请先登录或联系管理员"); } if (accessKeyStrings == null || accessKeyStrings.Length < 1) { throw new UnauthorizedAccessException("请求的资源没有权限,请先登录或联系管理员"); } string accessKey = Encryption.MD5Encrypt(Encryption.key + timeStampStrings[0]); //判断密钥是否正确 string key = accessKeyStrings.FirstOrDefault(item => item == accessKey); if (!string.IsNullOrEmpty(key)) { // 读取请求body中的数据 string baseContent = request.Content.ReadAsStringAsync().Result; // 获取加密的信息 // 兼容 body: 加密数据 和 body: code=加密数据 baseContent = baseContent.Match("(code=)*(?<code>[\\S]+)", 2); // 用加密对象解密数据 baseContent = Encryption.Decrypt3DES(baseContent, key); string baseQuery = string.Empty; if (!string.IsNullOrEmpty(request.RequestUri.Query)) { // 读取请求 url query数据 baseQuery = request.RequestUri.Query.Substring(1); baseQuery = baseQuery.Match("(code=)*(?<code>[\\S]+)", 2); baseQuery = Encryption.Decrypt3DES(baseQuery, key); } // 将解密后的 URL 重置URL请求 request.RequestUri = new Uri(request.RequestUri.AbsoluteUri.Split('?')[0] + "?" + baseQuery); // 将解密后的BODY数据 重置 var result = JsonConvert.DeserializeObject(baseContent); request.Content = new ObjectContent(typeof (object), result, new JsonMediaTypeFormatter()); return request; } throw new UnauthorizedAccessException("请求的资源没有权限,请先登录或联系管理员"); } /// <summary> /// 获取客户端IP地址 /// </summary> /// <returns></returns> public static string GetIP() { string result = HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"]; if (string.IsNullOrEmpty(result)) { result = HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"]; } if (string.IsNullOrEmpty(result)) { result = HttpContext.Current.Request.UserHostAddress; } if (string.IsNullOrEmpty(result)) { return "0.0.0.0"; } return result; } protected override HttpResponseMessage ProcessResponse(HttpResponseMessage response, System.Threading.CancellationToken cancellationToken) { try { //是否加密 string[] isEncrypt = HttpContext.Current.Request.Headers.GetValues("isEncrypt"); if (isEncrypt == null || isEncrypt.Length == 0 || string.IsNullOrWhiteSpace(isEncrypt[0]) || isEncrypt[0] == 0.ToString()) { return response; } //密钥 string[] accessKeyStrings = HttpContext.Current.Request.Headers.GetValues("accessKey"); if (accessKeyStrings == null || accessKeyStrings.Length < 1) { throw new UnauthorizedAccessException("请求的资源没有权限,请先登录或联系管理员"); } string result = null; if (response.Content != null) { result = response.Content.ReadAsStringAsync().Result; string encodeResult = Encryption.Encrypt3DES(result, accessKeyStrings.First()); response.Content = new StringContent(encodeResult); } return response; } catch (Exception e) { throw e; } } }
MD5
#region MD5加密 /// <summary> /// MD5加密 /// </summary> /// <param name="str">欲加密的明文</param> /// <returns>加密后的密文</returns> public static string MD5Encrypt(string str,string encodeName=null) { string ret = string.Empty; System.Security.Cryptography.MD5 md5 = new MD5CryptoServiceProvider(); Encoding encode = System.Text.Encoding.Default; if (!string.IsNullOrWhiteSpace(encodeName)) { try { var en = Encoding.GetEncoding(encodeName); if (en != null) encode = en; }catch{} } byte[] data = encode.GetBytes(str); byte[] result = md5.ComputeHash(data); for (int i = 0; i < result.Length; i++) { ret += result[i].ToString("x").PadLeft(2, '0'); } return ret; } /// <summary> /// MD5加密 /// </summary> /// <param name="str"></param> /// <returns></returns> public static string md5EncryptByUTF8(string str) { return Encryption.MD5Encrypt(str, "utf-8"); } #endregion
HttpClient辅助类
/// <summary> /// 返回一个设置了基本参数的HttpClient /// </summary> /// <returns></returns> public static HttpClient GetHttpClient() { var handler = new HttpClientHandler() { }; //UseProxy = true, Proxy = WebRequest.DefaultWebProxy if (!string.IsNullOrEmpty(ClientPublicData.LoginToken)) { //把验证需要的token放到cookie中 handler.CookieContainer = new CookieContainer(); handler.CookieContainer.Add(new Uri(WebApiClientConfiguration.MyWebApiBaseAddress), new Cookie(WebApiClientConfiguration.TokenCookieName, ClientPublicData.LoginToken)); } //HttpClient httpClient = HttpClientFactory.Create(handler, new LogHandler()); HttpClient httpClient = HttpClientFactory.Create(handler); httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); //httpClient.DefaultRequestHeaders.AcceptEncoding.Add(new StringWithQualityHeaderValue("gzip")); //httpClient.DefaultRequestHeaders.Add("X-UserAgent", "CSClient"); httpClient.BaseAddress = new Uri(WebApiClientConfiguration.MyWebApiBaseAddress); //httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", AuthorizationValue); //Basic验证方式 //httpClient.Timeout = new TimeSpan(0, 5, 0);//5分钟超时 return httpClient; } /// <summary> /// 根据Http状态代码抛出异常 /// </summary> /// <param name="statusCode"></param> public static void ThrowException(HttpStatusCode statusCode) { switch (statusCode) { case HttpStatusCode.OK: return;//正常代码 case HttpStatusCode.Unauthorized: throw new UnauthorizedAccessException("请求的资源没有权限,请先登录或联系管理员"); case HttpStatusCode.NotFound: throw new Exception("请求的资源不在服务器上[404]"); case HttpStatusCode.RequestTimeout: throw new Exception("请求超时[408]"); case HttpStatusCode.InternalServerError: throw new Exception("服务器上发生了一般错误[500]"); default: throw new Exception("请求时发生错误:" + statusCode.ToString() + "[" + (int)statusCode + "]"); } } #region 异步方法 /// <summary> /// 封装对服务器url的Post请求 /// </summary> /// <typeparam name="TResult">返回的结果</typeparam> /// <param name="url">请求的url地址</param> /// <param name="value">请求时传给服务器的参数</param> /// <param name="beforeAction">请求前要执行的代码,可为null</param> /// <param name="afterAction">请求后要执行的代码,可为null</param> /// <param name="isEncrypt">是否加密(1:代表加密,0代表不加密)</param> /// <returns></returns> public static async Task<TResult> PostAsJsonAsync<TResult>(string url, object value, Action beforeAction = null, Action afterAction = null, int isEncrypt=1) { url = url.TrimStart('/'); if (beforeAction != null) beforeAction(); try { using (var client = ApiClientHelper.GetHttpClient()) { client.DefaultRequestHeaders.Add("isEncrypt",isEncrypt.ToString()); //时间戳加密 string timeStamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:s"); string accessKey = Encryption.MD5Encrypt(Encryption.key + timeStamp); client.DefaultRequestHeaders.Add("timeStamp", timeStamp); client.DefaultRequestHeaders.Add("accessKey", accessKey); string constparam = null; if (isEncrypt==1) { //发送之前数据加密 if (value != null) { string param = JsonConvert.SerializeObject(value); constparam = Encryption.Encrypt3DES(param, accessKey); } string baseQuery = string.Empty; int index = url.IndexOf("?", System.StringComparison.Ordinal); if (index != -1) { baseQuery = url.Substring(index + 1); string starturl = url.Substring(0, index + 1); if (!string.IsNullOrEmpty(baseQuery)) { baseQuery = Encryption.Encrypt3DES(baseQuery, accessKey); url = starturl + baseQuery; } } } Task<HttpResponseMessage> aTask = client.PostAsJsonAsync<object>(url,isEncrypt==1?constparam:value); HttpResponseMessage response = await aTask; if (response.IsSuccessStatusCode) { string result1 = await response.Content.ReadAsStringAsync(); //解密 if (isEncrypt == 1) { result1 = Encryption.Decrypt3DES(result1, accessKey); } var result = JsonConvert.DeserializeObject<TResult>(result1); return result; } //response.EnsureSuccessStatusCode(); ThrowException(response.StatusCode); throw new Exception("请求时发生错误"); } } finally { if (afterAction != null) afterAction(); } } /// <summary> /// 封装对服务器url的Get请求 /// </summary> /// <typeparam name="TResult">返回的结果</typeparam> /// <param name="url">请求的url地址</param> /// <param name="beforeAction">请求前要执行的代码,可为null</param> /// <param name="afterAction">请求后要执行的代码,可为null</param> /// <param name="isEncrypt">是否加密(1:代表加密,0代表不加密)</param> /// <returns></returns> public static async Task<TResult> GetAsJsonAsync<TResult>(string url, Action beforeAction = null, Action afterAction = null,int isEncrypt=1) { url = url.TrimStart('/'); if (beforeAction != null) beforeAction(); try { using (var client = ApiClientHelper.GetHttpClient()) { client.DefaultRequestHeaders.Add("isEncrypt", isEncrypt.ToString()); //时间戳加密 string timeStamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:s"); string accessKey = Encryption.MD5Encrypt(Encryption.key + timeStamp); client.DefaultRequestHeaders.Add("timeStamp", timeStamp); client.DefaultRequestHeaders.Add("accessKey", accessKey); if (isEncrypt == 1) { //处理数据加密 string baseQuery = string.Empty; int index = url.IndexOf("?", System.StringComparison.Ordinal); if (index != -1) { baseQuery = url.Substring(index + 1); string starturl = url.Substring(0, index + 1); if (!string.IsNullOrEmpty(baseQuery)) { baseQuery = Encryption.Encrypt3DES(baseQuery, accessKey); url = starturl + baseQuery; } } } string result1 = await client.GetStringAsync(url); //处理数据解密 if (isEncrypt == 1) { result1 = Encryption.Decrypt3DES(result1, accessKey); } return JsonConvert.DeserializeObject<TResult>(result1); } } finally { if (afterAction != null) afterAction(); } } #endregion #region 同步方法 ///// <summary> ///// 封装对服务器url的Post请求 ///// </summary> ///// <typeparam name="TResult">返回的结果</typeparam> ///// <param name="url">请求的url地址</param> ///// <param name="value">请求时传给服务器的参数</param> ///// <returns></returns> //public static TResult PostAsJson<TResult>(string url, object value) //{ // url = url.TrimStart('/'); // using (var client = ApiClientHelper.GetHttpClient()) // { // HttpResponseMessage response = client.PostAsJsonAsync<object>(url, value).Result; // if (response.IsSuccessStatusCode) // { // TResult result = response.Content.ReadAsAsync<TResult>().Result; // return result; // } // //response.EnsureSuccessStatusCode(); // ThrowException(response.StatusCode); // throw new Exception("请求时发生错误"); // } //} /// <summary> /// 封装对服务器url的Get请求 /// </summary> /// <typeparam name="TResult">返回的结果</typeparam> /// <param name="url">请求的url地址</param> /// <returns></returns> public static TResult GetAsJson<TResult>(string url) { url = url.TrimStart('/'); using (var client = ApiClientHelper.GetHttpClient()) { string response = client.GetStringAsync(url).Result; return JsonConvert.DeserializeObject<TResult>(response); } } #endregion #region 上传下载文件 public static async Task<IList<VMCustLoanDocInfo>> UploadFile(List<VMCustLoanDocInfo> infos, List<FileStream> fileStreams) { List<VMCustLoanDocInfo> result = new List<VMCustLoanDocInfo>(); string url = "File/UploadByte"; Random random = new Random(int.Parse(DateTime.Now.ToString("HHmmss"))); int packSize = 30 + random.Next(10); int dataMaxLenth = packSize * 1024; for (int i = 0; i < infos.Count; i++) { DateTime nowFrom = DateTime.Now; var fileStream = fileStreams[i]; var info = infos[i]; string tmpGuid = Utility.Util.GetGuid(); byte[] bytes = new byte[dataMaxLenth]; int numBytesToRead = dataMaxLenth; int numBytesRead = 0; while (numBytesToRead > 0) { fileStream.Seek(numBytesRead, SeekOrigin.Begin); // Read may return anything from 0 to numBytesToRead. int n = 0; try { n = fileStream.Read(bytes, 0, numBytesToRead); } catch (Exception ee) { throw ee; } // Break when the end of the file is reached. if (n == 0) break; VMUploadData vmUpload = new VMUploadData() { TempGuid = tmpGuid, Seek = numBytesRead }; byte[] data = new byte[n]; Array.Copy(bytes, 0, data, 0, n); vmUpload.Data = data; //提交 byte isOK = 0; for (int repeatTimes = 1; repeatTimes <= 10; repeatTimes++) { //Console.WriteLine(repeatTimes); try { isOK = await ApiClientHelper.PostAsJsonAsync<byte>(url, vmUpload,null,null,0); } catch { } if (isOK == 1) break; } if (isOK != 1) { throw new Exception("上传" + info.DocName + "失败,请重试"); } numBytesRead += n; }//while string urlFinish = "File/UploadFinish"; VMUploadFinish vmFinish = new VMUploadFinish() { TempGuid = tmpGuid, VMDocInfo = info }; vmFinish.TotalUsedTime = DateTime.Now - nowFrom; VMCustLoanDocInfo tmpInfo = null; try { tmpInfo = await ApiClientHelper.PostAsJsonAsync<VMCustLoanDocInfo>(urlFinish, vmFinish,null,null,0); } catch { } if (null == tmpInfo) tmpInfo = await ApiClientHelper.PostAsJsonAsync<VMCustLoanDocInfo>(urlFinish, vmFinish,null,null,0); //重试 if (null == tmpInfo) { throw new Exception("上传" + info.DocName + "失败,请重试"); } result.Add(tmpInfo); }//for return result; }