激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - ASP.NET教程 - WebApi實現通訊加密

WebApi實現通訊加密

2020-04-22 14:13董僑 ASP.NET教程

本文主要介紹了WebApi實現通訊加密的方法,具有很好的參考價值,下面跟著小編一起來看下吧

一. 場景介紹:

如題如何有效的,最少量的現有代碼侵入從而實現客戶端與服務器之間的數據交換加密呢?

二. 探究:

1.需求分析

webapi服務端 有如下接口:

?
1
2
3
4
5
6
7
8
9
10
public class ApiTestController : ApiController
{
 // GET api/<controller>/5
 public object Get(int id)
 {
  return "value" + id;
 }
}
 
ApiTestController

無加密請求

GET /api/apitest?id=10

返回結果

response "value10"

我們想要達到的效果為:

Get /api/apitest?aWQ9MTA=
response InZhbHVlMTAi  (解密所得 "value10")

或者更多其它方式加密

2.功能分析

 要想對現有代碼不做任何修改, 我們都知道所有api controller 初始化在router確定之后, 因此我們應在router之前將GET參數和POST的參數進行加密才行.

看下圖 webapi 生命周期:

WebApi實現通訊加密

我們看到在 路由routing 之前 有DelegationgHander 層進行消息處理.

因為我們要對每個請求進行參數解密處理,并且又將返回消息進行加密處理, 因此我們 瞄準 MessageProcessingHandler

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
//
 // 摘要:
 //  A base type for handlers which only do some small processing of request and/or
 //  response messages.
 public abstract class MessageProcessingHandler : DelegatingHandler
 {
  //
  // 摘要:
  //  Creates an instance of a System.Net.Http.MessageProcessingHandler class.
  protected MessageProcessingHandler();
  //
  // 摘要:
  //  Creates an instance of a System.Net.Http.MessageProcessingHandler class with
  //  a specific inner handler.
  //
  // 參數:
  // innerHandler:
  //  The inner handler which is responsible for processing the HTTP response messages.
  protected MessageProcessingHandler(HttpMessageHandler innerHandler);
 
  //
  // 摘要:
  //  Performs processing on each request sent to the server.
  //
  // 參數:
  // request:
  //  The HTTP request message to process.
  //
  // cancellationToken:
  //  A cancellation token that can be used by other objects or threads to receive
  //  notice of cancellation.
  //
  // 返回結果:
  //  Returns System.Net.Http.HttpRequestMessage.The HTTP request message that was
  //  processed.
  protected abstract HttpRequestMessage ProcessRequest(HttpRequestMessage request, CancellationToken cancellationToken);
  //
  // 摘要:
  //  Perform processing on each response from the server.
  //
  // 參數:
  // response:
  //  The HTTP response message to process.
  //
  // cancellationToken:
  //  A cancellation token that can be used by other objects or threads to receive
  //  notice of cancellation.
  //
  // 返回結果:
  //  Returns System.Net.Http.HttpResponseMessage.The HTTP response message that was
  //  processed.
  protected abstract HttpResponseMessage ProcessResponse(HttpResponseMessage response, CancellationToken cancellationToken);
  //
  // 摘要:
  //  Sends an HTTP request to the inner handler to send to the server as an asynchronous
  //  operation.
  //
  // 參數:
  // request:
  //  The HTTP request message to send to the server.
  //
  // cancellationToken:
  //  A cancellation token that can be used by other objects or threads to receive
  //  notice of cancellation.
  //
  // 返回結果:
  //  Returns System.Threading.Tasks.Task`1.The task object representing the asynchronous
  //  operation.
  //
  // 異常:
  // T:System.ArgumentNullException:
  //  The request was null.
  protected internal sealed override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken);
 }
 
MessageProcessingHandler

三. 實踐:

現在我們將來 先實現2個版本的通訊加密解密功能,定為 版本1.0 base64加密, 版本1.1 Des加密

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/// <summary>
 /// 加密解密接口
 /// </summary>
 public interface IMessageEnCryption
 {
  /// <summary>
  /// 加密
  /// </summary>
  /// <param name="content"></param>
  /// <returns></returns>
  string Encode(string content);
  /// <summary>
  /// 解密
  /// </summary>
  /// <param name="content"></param>
  /// <returns></returns>
  string Decode(string content);
 }
 
IMessageEnCryption

編寫版本1.0 base64加密解密

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/// <summary>
 /// 加解密 只做 base64
 /// </summary>
 public class MessageEncryptionVersion1_0 : IMessageEnCryption
 {
  public string Decode(string content)
  {
   return content?.DecryptBase64();
  }
 
  public string Encode(string content)
  {
   return content.EncryptBase64();
  }
 }
 
MessageEncryptionVersion1_0

編寫版本1.1 des加密解密

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/// <summary>
 /// 數據加解密 des
 /// </summary>
 public class MessageEncryptionVersion1_1 : IMessageEnCryption
 {
  public static readonly string KEY = "fHil/4]0";
  public string Decode(string content)
  {
   return content.DecryptDES(KEY);
  }
  public string Encode(string content)
  {
   return content.EncryptDES(KEY);
  }
 }
 
MessageEncryptionVersion1_1

附上加密解密的基本的一個封裝類

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
public static class EncrypExtends
 {
  //默認密鑰向量
  private static byte[] Keys = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF };
  internal static string Key = "*@&$(@#H";
 
  //// <summary>
  /// DES加密字符串
  /// </summary>
  /// <param name="encryptString">待加密的字符串</param>
  /// <param name="encryptKey">加密密鑰,要求為8位</param>
  /// <returns>加密成功返回加密后的字符串,失敗返回源串</returns>
  public static string EncryptDES(this string encryptString, string encryptKey)
  {
   try
   {
    byte[] rgbKey = Encoding.UTF8.GetBytes(encryptKey.Substring(0, 8));
    byte[] rgbIV = Keys;
    byte[] inputByteArray = Encoding.UTF8.GetBytes(encryptString);
    DESCryptoServiceProvider dCSP = new DESCryptoServiceProvider();
    MemoryStream mStream = new MemoryStream();
    CryptoStream cStream = new CryptoStream(mStream, dCSP.CreateEncryptor(rgbKey, rgbIV), CryptoStreamMode.Write);
    cStream.Write(inputByteArray, 0, inputByteArray.Length);
    cStream.FlushFinalBlock();
    return Convert.ToBase64String(mStream.ToArray());
   }
   catch
   {
    return encryptString;
   }
  }
  //// <summary>
  /// DES解密字符串
  /// </summary>
  /// <param name="decryptString">待解密的字符串</param>
  /// <param name="decryptKey">解密密鑰,要求為8位,和加密密鑰相同</param>
  /// <returns>解密成功返回解密后的字符串,失敗返源串</returns>
  public static string DecryptDES(this string decryptString, string key)
  {
   try
   {
    byte[] rgbKey = Encoding.UTF8.GetBytes(key.Substring(0, 8));
    byte[] rgbIV = Keys;
    byte[] inputByteArray = Convert.FromBase64String(decryptString);
    DESCryptoServiceProvider DCSP = new DESCryptoServiceProvider();
    MemoryStream mStream = new MemoryStream();
    CryptoStream cStream = new CryptoStream(mStream, DCSP.CreateDecryptor(rgbKey, rgbIV), CryptoStreamMode.Write);
    cStream.Write(inputByteArray, 0, inputByteArray.Length);
    cStream.FlushFinalBlock();
    return Encoding.UTF8.GetString(mStream.ToArray());
   }
   catch
   {
    return decryptString;
   }
  }
  public static string EncryptBase64(this string encryptString)
  {
   return Convert.ToBase64String(Encoding.UTF8.GetBytes(encryptString));
  }
  public static string DecryptBase64(this string encryptString)
  {
   return Encoding.UTF8.GetString(Convert.FromBase64String(encryptString));
  }
  public static string DecodeUrl(this string cryptString)
  {
   return System.Web.HttpUtility.UrlDecode(cryptString);
  }
  public static string EncodeUrl(this string cryptString)
  {
   return System.Web.HttpUtility.UrlEncode(cryptString);
  }
 }
 
EncrypExtends

OK! 到此我們前題工作已經完成了80%,開始進行HTTP請求的 消息進和出的加密解密功能的實現.

我們暫時將加密的版本信息定義為 HTTP header頭中 以 api_version 的value 來判別分別是用何種方式加密解密

header例:

  api_version: 1.0

  api_version: 1.1

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
/// <summary>
 /// API消息請求處理
 /// </summary>
 public class JoyMessageHandler : MessageProcessingHandler
 {
  /// <summary>
  /// 接收到request時 處理
  /// </summary>
  /// <param name="request"></param>
  /// <param name="cancellationToken"></param>
  /// <returns></returns>
  protected override HttpRequestMessage ProcessRequest(HttpRequestMessage request, CancellationToken cancellationToken)
  {
   if (request.Content.IsMimeMultipartContent())
    return request;
   // 獲取請求頭中 api_version版本號
   var ver = System.Web.HttpContext.Current.Request.Headers.GetValues("api_version")?.FirstOrDefault();
   // 根據api_version版本號獲取加密對象, 如果為null 則不需要加密
   var encrypt = MessageEncryptionCreator.GetInstance(ver);
   if (encrypt != null)
   {
    // 讀取請求body中的數據
    string baseContent = request.Content.ReadAsStringAsync().Result;
    // 獲取加密的信息
    // 兼容 body: 加密數據 和 body: code=加密數據
    baseContent = baseContent.Match("(code=)*(?<code>[\\S]+)", 2);
    // URL解碼數據
    baseContent = baseContent.DecodeUrl();
    // 用加密對象解密數據
    baseContent = encrypt.Decode(baseContent);
    string baseQuery = string.Empty;
    if (!request.RequestUri.Query.IsNullOrEmpty())
    {
     // 同 body
     // 讀取請求 url query數據
     baseQuery = request.RequestUri.Query.Substring(1);
     baseQuery = baseQuery.Match("(code=)*(?<code>[\\S]+)", 2);
     baseQuery = baseQuery.DecodeUrl();
     baseQuery = encrypt.Decode(baseQuery);
    }
    // 將解密后的 URL 重置URL請求
    request.RequestUri = new Uri($"{request.RequestUri.AbsoluteUri.Split('?')[0]}?{baseQuery}");
    // 將解密后的BODY數據 重置
    request.Content = new StringContent(baseContent);
   }
   return request;
  }
  /// <summary>
  /// 處理將要向客戶端response時
  /// </summary>
  /// <param name="response"></param>
  /// <param name="cancellationToken"></param>
  /// <returns></returns>
  protected override HttpResponseMessage ProcessResponse(HttpResponseMessage response, CancellationToken cancellationToken)
  {
   //var isMediaType = response.Content.Headers.ContentType.MediaType.Equals(mediaTypeName, StringComparison.OrdinalIgnoreCase);
   var ver = System.Web.HttpContext.Current.Request.Headers.GetValues("api_version")?.FirstOrDefault();
   var encrypt = MessageEncryptionCreator.GetInstance(ver);
   if (encrypt != null)
   {
    if (response.StatusCode == HttpStatusCode.OK)
    {
     var result = response.Content.ReadAsStringAsync().Result;
     // 返回消息 進行加密
     var encodeResult = encrypt.Encode(result);
     response.Content = new StringContent(encodeResult);
    }
   }
   return response;
  }
 }
 
JoyMessageHandler

最后在 webapiconfig 中將我們的消息處理添加到容器中

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public static class WebApiConfig
 {
  public static void Register(HttpConfiguration config)
  {
   // Web API 配置和服務
   // 將 Web API 配置為僅使用不記名令牌身份驗證。
   config.SuppressDefaultHostAuthentication();
   config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
   // Web API 路由
   config.MapHttpAttributeRoutes();
   config.Routes.MapHttpRoute(
    name: "DefaultApi",
    routeTemplate: "api/{controller}/{id}",
    defaults: new { id = RouteParameter.Optional }
   );
   // 添加自定義消息處理
   config.MessageHandlers.Add(new JoyMessageHandler());
  }
 }
 
WebApiConfig

編寫單元測試:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
[TestMethod()]
  public void GetTest()
  {
   var id = 10;
   var resultSuccess = $"\"value{id}\"";
   //不加密
   Trace.WriteLine($"without encryption.");
   var url = $"api/ApiTest?id={id}";
   Trace.WriteLine($"get url : {url}");
   var response = http.GetAsync(url).Result;
   var result = response.Content.ReadAsStringAsync().Result;
   Assert.AreEqual(result, resultSuccess);
   Trace.WriteLine($"result : {result}");
   //使用 方案1加密
   Trace.WriteLine($"encryption case one.");
   url = $"api/ApiTest?code=" + $"id={id}".EncryptBase64().EncodeUrl();
   Trace.WriteLine($"get url : {url}");
   http.DefaultRequestHeaders.Clear();
   http.DefaultRequestHeaders.Add("api_version", "1.0");
   response = http.GetAsync(url).Result;
   result = response.Content.ReadAsStringAsync().Result;
   Trace.WriteLine($"result : {result}");
   result = result.DecryptBase64();
   Trace.WriteLine($"DecryptBase64 : {result}");
   Assert.AreEqual(result, resultSuccess);
   //使用 方案2 加密通訊
   Trace.WriteLine($"encryption case one.");
   url = $"api/ApiTest?code=" + $"id={id}".EncryptDES(MessageEncryptionVersion1_1.KEY).EncodeUrl();
   Trace.WriteLine($"get url : {url}");
   http.DefaultRequestHeaders.Clear();
   http.DefaultRequestHeaders.Add("api_version", "1.1");
   response = http.GetAsync(url).Result;
   result = response.Content.ReadAsStringAsync().Result;
   Trace.WriteLine($"result : {result}");
   result = result.DecryptDES(MessageEncryptionVersion1_1.KEY);
   Trace.WriteLine($"DecryptBase64 : {result}");
   Assert.AreEqual(result, resultSuccess);
  }
 
ApiTestControllerTests

至此為止功能實現完畢..

四.思想延伸

要想更加安全的方案,可以將給每位用戶生成不同的 private key , 利用AES加密解密

本Demo開源地址:

oschina

https://git.oschina.net/jonneydong/Webapi_Encryption

github

https://github.com/JonneyDong/Webapi_Encryption

以上就是本文的全部內容,希望本文的內容對大家的學習或者工作能帶來一定的幫助,同時也希望多多支持服務器之家!

原文鏈接:http://www.cnblogs.com/jonneydong/p/WebApi_Encryption.html

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 国产成人精品免费视频大全最热 | 国产91对白叫床清晰播放 | 嫩草影院在线观看网站成人 | 亚洲成人精品久久 | 亚洲一区二区免费 | 国产一区二区视频精品 | 史上最强炼体老祖动漫在线观看 | 免费国产在线视频 | 国产免费一级大片 | 免费黄网站在线播放 | 色骚综合| 国产高潮失禁喷水爽到抽搐视频 | 国产精品久久久久久久久久久久久久久 | 免费一级特黄做受大片 | 激情小说激情图片激情电影 | 黑人一区二区 | 精品国产一区二区三区四区在线 | 国产精品看片 | 九九热免费视频在线观看 | 午夜精品久久久久久毛片 | 精品国产一区二区亚洲人成毛片 | 九九热视频这里只有精品 | 日韩免费黄色 | 性大片免费看 | 毛片在线免费 | 91精品视频免费 | 国产女同玩人妖 | 激情国产视频 | 国产精品久久久久久久久久久久午夜 | 成人av一区二区免费播放 | 久草在线新视觉 | 国产精品免费视频观看 | 曰韩黄色片| freexxxhd喷水 | 亚洲二区不卡 | 在线无码 | 成人久久久精品国产乱码一区二区 | 久久久久亚洲a | 美女福利视频国产 | 在线观看国产一区二区三区 | 美女网站色免费 |