search
HomeBackend DevelopmentC#.Net TutorialWebApi implements communication encryption

1. ScenarioIntroduction:

How to effectively achieve data exchange between the client and the service with the minimum amount of existing code intrusion What about encryption?

2. Exploration:

1. Requirements analysis

webapiThe server has the following Interface:


##

public class ApiTestController : ApiController
{    // GET api/<controller>/5
    public object Get(int id)
    {        return "value" + id;
    }
}</controller>

ApiTestController

Unencrypted request

GET /api/apitest?id=10

Return result

response "value10"

We want The effect achieved is:

Get /api/apitest?aWQ9MTA=

response InZhbHVlMTAi (decryption result "value10")

or MoreOthermethods of encryption

2. Functional analysis

If you want to make no changes to the existing code, we all know All api controllers are initialized after the router is determined, so we should encrypt the GET parameters and POST parameters before the router.

Look at the picture below webapi Life cycle:

We see that there is a DelegationgHander layer for message processing before routingrouting.

Because we need to decrypt the parameters of each request and encrypt the return message, we aim at 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);
    }</httpresponsemessage>

MessageProcessingHandler

3. Practice:

Now we will implement it in the future Two versions of communication encryption and decryption functions, designated as version 1.0 base64 encryption and version 1.1 Des encryption

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

IMessageEnCryption

Writing version 1.0 base64 encryption and decryption

 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     }

MessageEncryptionVersion1_0

Writing version 1.1 des encryption and decryption

##

 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     }

MessageEncryptionVersion1_1

Attach encryption and decryption A basic encapsulation class


 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>待加密的字符串12         /// <param>加密密钥,要求为8位13         /// <returns>加密成功返回加密后的字符串,失败返回源串</returns>14         public static string EncryptDES(this string encryptString, string encryptKey)15         {16             try17             {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             catch29             {30                 return encryptString;31             }32         }33         //// <summary>34         /// DES解密字符串35         /// </summary>36         /// <param>待解密的字符串37         /// <param>解密密钥,要求为8位,和加密密钥相同38         /// <returns>解密成功返回解密后的字符串,失败返源串</returns>39         public static string DecryptDES(this string decryptString, string key)40         {41             try42             {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             catch54             {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)71         {72             return System.Web.HttpUtility.UrlEncode(cryptString);73         }74     }

EncrypExtends

OK! 到此我们前题工作已经完成了80%,开始进行HTTP请求的 消息进和出的加密解密功能的实现.

我们暂时将加密的版本信息定义为 HTTP header头中 以 api_version 的value 来判别分别是用何种方式加密解密

header例:

  api_version: 1.0

  api_version: 1.1

 


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

JoyMessageHandler

 

最后在 webapiconfig 中将我们的消息处理添加到容器中

 


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

WebApiConfig

 

编写单元测试:


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

ApiTestControllerTests

 至此为止功能实现完毕..

 四.思想延伸

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

 

The above is the detailed content of WebApi implements communication encryption. For more information, please follow other related articles on the PHP Chinese website!

Statement
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
How to use char array in C languageHow to use char array in C languageApr 03, 2025 pm 03:24 PM

The char array stores character sequences in C language and is declared as char array_name[size]. The access element is passed through the subscript operator, and the element ends with the null terminator '\0', which represents the end point of the string. The C language provides a variety of string manipulation functions, such as strlen(), strcpy(), strcat() and strcmp().

How to handle special characters in C languageHow to handle special characters in C languageApr 03, 2025 pm 03:18 PM

In C language, special characters are processed through escape sequences, such as: \n represents line breaks. \t means tab character. Use escape sequences or character constants to represent special characters, such as char c = '\n'. Note that the backslash needs to be escaped twice. Different platforms and compilers may have different escape sequences, please consult the documentation.

What is the role of char in C stringsWhat is the role of char in C stringsApr 03, 2025 pm 03:15 PM

In C, the char type is used in strings: 1. Store a single character; 2. Use an array to represent a string and end with a null terminator; 3. Operate through a string operation function; 4. Read or output a string from the keyboard.

How to use various symbols in C languageHow to use various symbols in C languageApr 03, 2025 pm 04:48 PM

The usage methods of symbols in C language cover arithmetic, assignment, conditions, logic, bit operators, etc. Arithmetic operators are used for basic mathematical operations, assignment operators are used for assignment and addition, subtraction, multiplication and division assignment, condition operators are used for different operations according to conditions, logical operators are used for logical operations, bit operators are used for bit-level operations, and special constants are used to represent null pointers, end-of-file markers, and non-numeric values.

The difference between multithreading and asynchronous c#The difference between multithreading and asynchronous c#Apr 03, 2025 pm 02:57 PM

The difference between multithreading and asynchronous is that multithreading executes multiple threads at the same time, while asynchronously performs operations without blocking the current thread. Multithreading is used for compute-intensive tasks, while asynchronously is used for user interaction. The advantage of multi-threading is to improve computing performance, while the advantage of asynchronous is to not block UI threads. Choosing multithreading or asynchronous depends on the nature of the task: Computation-intensive tasks use multithreading, tasks that interact with external resources and need to keep UI responsiveness use asynchronous.

How to convert char in C languageHow to convert char in C languageApr 03, 2025 pm 03:21 PM

In C language, char type conversion can be directly converted to another type by: casting: using casting characters. Automatic type conversion: When one type of data can accommodate another type of value, the compiler automatically converts it.

What is the function of C language sum?What is the function of C language sum?Apr 03, 2025 pm 02:21 PM

There is no built-in sum function in C language, so it needs to be written by yourself. Sum can be achieved by traversing the array and accumulating elements: Loop version: Sum is calculated using for loop and array length. Pointer version: Use pointers to point to array elements, and efficient summing is achieved through self-increment pointers. Dynamically allocate array version: Dynamically allocate arrays and manage memory yourself, ensuring that allocated memory is freed to prevent memory leaks.

Avoid errors caused by default in C switch statementsAvoid errors caused by default in C switch statementsApr 03, 2025 pm 03:45 PM

A strategy to avoid errors caused by default in C switch statements: use enums instead of constants, limiting the value of the case statement to a valid member of the enum. Use fallthrough in the last case statement to let the program continue to execute the following code. For switch statements without fallthrough, always add a default statement for error handling or provide default behavior.

See all articles

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

AI Hentai Generator

AI Hentai Generator

Generate AI Hentai for free.

Hot Article

R.E.P.O. Energy Crystals Explained and What They Do (Yellow Crystal)
3 weeks agoBy尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Best Graphic Settings
3 weeks agoBy尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. How to Fix Audio if You Can't Hear Anyone
3 weeks agoBy尊渡假赌尊渡假赌尊渡假赌

Hot Tools

SublimeText3 Linux new version

SublimeText3 Linux new version

SublimeText3 Linux latest version

Atom editor mac version download

Atom editor mac version download

The most popular open source editor

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

Powerful PHP integrated development environment

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

VSCode Windows 64-bit Download

VSCode Windows 64-bit Download

A free and powerful IDE editor launched by Microsoft