WebApi实现通讯加密
一. 场景介绍:
如题如何有效的,最少量的现有代码侵入从而实现客户端与服务器之间的数据交换加密呢?
二. 探究:
1.需求分析
webapi服务端 有如下接口:
public class ApiTestController : ApiController
{
// GET api/<controller>/5
public object Get(int id)
{
return "value" + id;
}
}
无加密请求
GET /api/apitest?id=10
返回结果
response "value10"
我们想要达到的效果为:
Get /api/apitest?aWQ9MTA=
response InZhbHVlMTAi (解密所得 "value10")
或者更多其它方式加密
2.功能分析
要想对现有代码不做任何修改, 我们都知道所有api controller 初始化在router确定之后, 因此我们应在router之前将GET参数和POST的参数进行加密才行.
看下图 webapi 生命周期:
我们看到在 路由routing 之前 有DelegationgHander 层进行消息处理.
因为我们要对每个请求进行参数解密处理,并且又将返回消息进行加密处理, 因此我们 瞄准 MessageProcessingHandler
//
// 摘要:
// 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);
}
三. 实践:
现在我们将来 先实现2个版本的通讯加密解密功能,定为 版本1.0 base64加密, 版本1.1 Des加密
1 /// <summary>
2 /// 加密解密接口
3 /// </summary>
4 public interface IMessageEnCryption
5 {
6 /// <summary>
7 /// 加密
8 /// </summary>
9 /// <param name="content"></param>
10 /// <returns></returns>
11 string Encode(string content);
12 /// <summary>
13 /// 解密
14 /// </summary>
15 /// <param name="content"></param>
16 /// <returns></returns>
17 string Decode(string content);
18 }
编写版本1.0 base64加密解密
1 /// <summary>
2 /// 加解密 只做 base64
3 /// </summary>
4 public class MessageEncryptionVersion1_0 : IMessageEnCryption
5 {
6 public string Decode(string content)
7 {
8 return content?.DecryptBase64();
9 }
10
11 public string Encode(string content)
12 {
13 return content.EncryptBase64();
14 }
15 }
编写版本1.1 des加密解密
1 /// <summary>
2 /// 数据加解密 des
3 /// </summary>
4 public class MessageEncryptionVersion1_1 : IMessageEnCryption
5 {
6 public static readonly string KEY = "fHil/4]0";
7 public string Decode(string content)
8 {
9 return content.DecryptDES(KEY);
10 }
11
12 public string Encode(string content)
13 {
14 return content.EncryptDES(KEY);
15 }
16 }
附上加密解密的基本的一个封装类
1 public static class EncrypExtends
2 {
3
4 //默认密钥向量
5 private static byte[] Keys = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF };
6 internal static string Key = "*@&$(@#H";
7
8 //// <summary>
9 /// DES加密字符串
10 /// </summary>
11 /// <param name="encryptString">待加密的字符串</param>
12 /// <param name="encryptKey">加密密钥,要求为8位</param>
13 /// <returns>加密成功返回加密后的字符串,失败返回源串</returns>
14 public static string EncryptDES(this string encryptString, string encryptKey)
15 {
16 try
17 {
18 byte[] rgbKey = Encoding.UTF8.GetBytes(encryptKey.Substring(0, 8));
19 byte[] rgbIV = Keys;
20 byte[] inputByteArray = Encoding.UTF8.GetBytes(encryptString);
21 DESCryptoServiceProvider dCSP = new DESCryptoServiceProvider();
22 MemoryStream mStream = new MemoryStream();
23 CryptoStream cStream = new CryptoStream(mStream, dCSP.CreateEncryptor(rgbKey, rgbIV), CryptoStreamMode.Write);
24 cStream.Write(inputByteArray, 0, inputByteArray.Length);
25 cStream.FlushFinalBlock();
26 return Convert.ToBase64String(mStream.ToArray());
27 }
28 catch
29 {
30 return encryptString;
31 }
32 }
33 //// <summary>
34 /// DES解密字符串
35 /// </summary>
36 /// <param name="decryptString">待解密的字符串</param>
37 /// <param name="decryptKey">解密密钥,要求为8位,和加密密钥相同</param>
38 /// <returns>解密成功返回解密后的字符串,失败返源串</returns>
39 public static string DecryptDES(this string decryptString, string key)
40 {
41 try
42 {
43 byte[] rgbKey = Encoding.UTF8.GetBytes(key.Substring(0, 8));
44 byte[] rgbIV = Keys;
45 byte[] inputByteArray = Convert.FromBase64String(decryptString);
46 DESCryptoServiceProvider DCSP = new DESCryptoServiceProvider();
47 MemoryStream mStream = new MemoryStream();
48 CryptoStream cStream = new CryptoStream(mStream, DCSP.CreateDecryptor(rgbKey, rgbIV), CryptoStreamMode.Write);
49 cStream.Write(inputByteArray, 0, inputByteArray.Length);
50 cStream.FlushFinalBlock();
51 return Encoding.UTF8.GetString(mStream.ToArray());
52 }
53 catch
54 {
55 return decryptString;
56 }
57 }
58 public static string EncryptBase64(this string encryptString)
59 {
60 return Convert.ToBase64String(Encoding.UTF8.GetBytes(encryptString));
61 }
62 public static string DecryptBase64(this string encryptString)
63 {
64 return Encoding.UTF8.GetString(Convert.FromBase64String(encryptString));
65 }
66 public static string DecodeUrl(this string cryptString)
67 {
68 return System.Web.HttpUtility.UrlDecode(cryptString);
69 }
70 public static string EncodeUrl(this string cryptString)