WebApi는 클라이언트와 서버 간의 데이터 교환 암호화를 구현합니다.
本文主要介绍了WebApi实现通讯加密的方法,具有很好的参考价值,下面跟着小编一起来看下吧
一. 场景介绍:
如题如何有效的,最少量的现有代码侵入从而实现客户端与服务器之间的数据交换加密呢?
二. 探究:
1.需求分析
webapi服务端 有如下接口:
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 生命周期:
我们看到在 路由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); } MessageProcessingHandler
三. 实践:
现在我们将来 先实现2个版本的通讯加密解密功能,定为 版本1.0 base64加密, 版本1.1 Des加密
/// <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加密解密
/// <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加密解密
/// <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
附上加密解密的基本的一个封装类
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
/// <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 中将我们的消息处理添加到容器中
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
编写单元测试:
[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加密解密
【相关推荐】
위 내용은 WebApi는 클라이언트와 서버 간의 데이터 교환 암호화를 구현합니다.의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

드림위버 CS6
시각적 웹 개발 도구

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

뜨거운 주제











Bitlocker는 Windows 운영 체제의 기본 암호화 기술입니다. Windows에서 널리 사용되지만 일부 사용자는 VeraCrypt와 같은 타사 솔루션을 선호합니다. Bitlocker의 많은 사용자는 256비트를 사용할 수 있음에도 불구하고 기본적으로 128비트 암호화로 설정된다는 사실을 모르고 있습니다. AES 128비트 암호화와 256비트 암호화의 핵심 차이점은 보안 키의 길이입니다. 키가 길수록 무차별 대입 공격이 더 어려워집니다. 기본값은 128비트이지만 Microsoft에서도 보안 강화를 위해 256비트를 권장합니다. 문제는 대부분의 사용자가 더 약한 기본값이나 이를 변경하는 방법을 모른다는 것입니다. 먼저 W를 알고 싶을 수도 있습니다.

Microsoft는 이전에 win11에 대한 DNS 암호화 서비스를 제공했지만 많은 사용자는 win11 암호화된 DNS를 사용하는 방법을 모릅니다. 실제로 네트워크 설정에서 DNS 설정만 열면 됩니다. win11 암호화된 DNS에 대한 자세한 튜토리얼: 1. 먼저 디스크에 들어가서 암호화하려는 폴더를 찾으십시오. 2. 그런 다음 오른쪽의 "이더넷"을 엽니다. 3. 그런 다음 아래의 DNS 서버 할당을 찾아 "편집"을 클릭합니다. 4. "자동(DHCP)"을 "수동"으로 변경한 후 아래의 "IPv4"를 엽니다. 5. 켠 후 , 기본 DNS에 "8.8.8.8"을 입력합니다. 6. 그런 다음 기본 DNS 암호화를 "암호화만(DNS over HTTPS)"로 변경합니다. 7. 변경이 완료된 후 "저장"을 클릭하면 다음을 찾을 수 있습니다.

파일 암호화는 데이터 보안을 보다 효과적으로 보장하기 위해 전문가 수준의 데이터 암호화를 구현하는 것을 목표로 합니다! 올바른 암호화 키를 마스터해야만 해독 작업을 수행할 수 있어 정보 자산의 보안이 보장됩니다. 하지만 Win10 Home Edition의 파일 암호화 기능에는 아직 이 기능이 없습니다. Win10 Home Edition은 폴더를 암호화할 수 있습니까? 대답: Win10 Home Edition은 폴더를 암호화할 수 없습니다. Windows 시스템에서 파일 암호화 튜토리얼 1. 암호화하려는 파일 또는 폴더를 마우스 오른쪽 버튼으로 클릭한 후(또는 잠시 누르고 있음) "속성" 기능을 선택합니다. 2. 새로운 확장 인터페이스에서 '고급' 옵션을 찾아 들어가신 후 아래에 있는 '데이터를 보호하기 위해 콘텐츠 암호화' 옵션을 선택하세요. 3. 설정이 완료되면 "확인"을 클릭하여

Apple 휴대폰에서 사용자는 필요에 따라 사진 앨범을 암호화할 수 있습니다. 일부 사용자는 설정 방법을 모릅니다. 암호화해야 할 사진을 메모에 추가한 후 메모를 잠글 수 있습니다. 다음으로 관심 있는 사용자들을 위해 편집자가 모바일 사진 앨범 암호화 설정 방법을 소개합니다. Apple 휴대폰 튜토리얼 iPhone 사진 앨범 암호화 설정 방법 A: 암호화해야 할 사진을 메모에 추가한 후 자세한 소개를 위해 메모 잠금으로 이동합니다. 1. 사진 앨범에 들어가서 암호화해야 할 사진을 선택합니다. 암호화한 후 아래의 [추가]를 클릭하세요. 2. [메모에 추가]를 선택하세요. 3. 메모를 입력하고, 방금 작성한 메모를 찾아 입력한 후 오른쪽 상단의 [보내기] 아이콘을 클릭하세요. 4. 아래 [기기 잠금]을 클릭하세요.

폴더 암호화는 복호화 비밀번호를 아는 사람만 파일에 액세스할 수 있도록 폴더의 내용을 암호화하는 일반적인 데이터 보호 방법입니다. 폴더를 암호화할 때 파일을 압축하지 않고 비밀번호를 설정하는 몇 가지 일반적인 방법이 있습니다. 먼저, 운영 체제와 함께 제공되는 암호화 기능을 사용하여 폴더 비밀번호를 설정할 수 있습니다. Windows 사용자의 경우 다음 단계에 따라 설정할 수 있습니다. 암호화할 폴더를 선택하고 해당 폴더를 마우스 오른쪽 버튼으로 클릭한 후 "속성"을 선택합니다.

C#의 일반적인 네트워크 통신 및 보안 문제와 해결 방법 오늘날 인터넷 시대에 네트워크 통신은 소프트웨어 개발에 없어서는 안 될 부분이 되었습니다. C#에서는 일반적으로 데이터 전송 보안, 네트워크 연결 안정성 등과 같은 일부 네트워크 통신 문제가 발생합니다. 이 문서에서는 C#의 일반적인 네트워크 통신 및 보안 문제에 대해 자세히 설명하고 해당 솔루션과 코드 예제를 제공합니다. 1. 네트워크 통신 문제 네트워크 연결 중단: 네트워크 통신 과정에서 네트워크 연결이 중단될 수 있으며, 이로 인해

PHP 암호화 및 암호 해독 기능의 전체 목록: md5, sha1, base64_encode 및 기타 기능의 안전한 응용 방법(특정 코드 예제가 필요함)은 네트워크 응용 프로그램 개발에서 데이터 암호화 및 암호 해독이 매우 중요합니다. 널리 사용되는 서버 측 스크립팅 언어인 PHP는 다양한 암호화 및 암호 해독 기능을 제공합니다. 이 기사에서는 일반적으로 사용되는 기능과 보안 적용 방법을 소개하고 구체적인 코드 예제를 제공합니다. md5 함수 md5 함수는 모든 길이의 문자열을 32비트로 변환할 수 있는 가장 일반적인 암호화 함수입니다.

일부 친구는 파일을 보호하고 싶지만 win11 문서를 암호화하는 방법을 모릅니다. 실제로 폴더 암호화를 사용하거나 타사 소프트웨어를 사용하여 파일을 암호화할 수 있습니다. win11 문서 암호화에 대한 자세한 튜토리얼: 1. 먼저 암호화하려는 파일을 찾아 마우스 오른쪽 버튼으로 클릭하여 선택한 다음 "속성"을 엽니다. 2. 그런 다음 속성 열에서 "고급"을 클릭합니다. 3. "데이터를 보호하기 위해 콘텐츠 암호화"를 선택합니다. "를 클릭하고 "확인"을 클릭합니다. 4. 그런 다음 "확인"을 클릭하여 저장합니다. 5. 마지막으로 원하는 암호화 모드를 선택하고 "확인"을 눌러 문서를 암호화하여 저장합니다.
