webAPI请求消息过滤器

每当制作一个WebAPI,就必然会收到外部很多调用这个API的请求,有时候,我们希望,能从这些外部来的请求中,按照一定条件筛选过滤一下,只将那些我们觉得合法的,有必要回应的请求放进来,一方面挡住那些非法请求,一方面也可以节省服务器应付无效请求的资源这个时候,我们就需要创建一个过滤器碰巧,前几年给之前某家公司做webapi的时候,钻研过这部分,刚好让我找到了一个在请求到达controller之前过滤掉的办法好了,废话不多说,直奔主题,这个过滤器的核心就是一个messageHandler,至于它是怎么起到过滤的作用,这方面的原理,我就不详述了,想知道的同学自己在网上找找,因为我也记不得太详细既然核心是一个messageHandler,那么首先就是要创建一个Handler类,如下图我给这个Handler类起名叫CustomHandler(当然叫别的名字也可以,这个随个人喜好),接下来,就是核心代码部分了
  1 using System;
  2 using System.Collections.Generic;
  3 using System.Linq;
  4 using System.Net.Http;
  5 using System.ServiceModel.Channels;
  6 using System.Text;
  9 using System.Threading.Tasks;
 10 using System.Net;
 11 using System.Collections.Specialized;
 12 using System.Web;
 13 using System.Data;
 14 using System.Data.SqlClient;
 15 
 16 namespace WebApi.User.Handler
 17 {
 18     public class CustomHandler : DelegatingHandler
 19     {
 20         public string message = "";
 21 
 22         protected override System.Threading.Tasks.Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
 23         {
 24             string method = request.Method.ToString();            
 25 
 26             string ip = "UnKnow";                      
 27 
 28             Uri uri = request.RequestUri;
 29 
 30             HttpContextBase contextBase = (HttpContextBase)request.Properties["MS_HttpContext"];
 31 
 32             HttpRequestBase requestBase = contextBase.Request;
 33 
 34             if (requestBase.UserHostAddress!="")
 35             {
 36                 ip = requestBase.UserHostAddress;
 37             }
 38 
 39             SignInfo signInfo = InitSignInfo(requestBase);
 40             signInfo.Method = method;
 41 
 42             if (ValidateRequest(signInfo))
 43             {
 44                 if (ValidUser(signInfo))
 45                 {
 46                     return base.SendAsync(request, cancellationToken).ContinueWith((task) =>
 47                     {
 48                         HttpResponseMessage resp = task.Result as HttpResponseMessage;
 49                         message = "正常";
 50                         //记录日志
 51                         string loginfo = string.Format("{0}  {1}  {2}  {3}", message, method, uri.ToString(), (int)resp.StatusCode);
 52                         LogHelper.WriteInfo(signInfo.PublicKey, signInfo.ApiName, ip, loginfo, (int)resp.StatusCode, message);
 53 
 54                         return resp;
 55                     });
 56                 }
 57                 else
 58                 {
 59                     //message = "无权访问";
 60                     //记录日志
 61                     string loginfo = string.Format("{0}  {1}  {2}  {3}", message, method, uri.ToString(), (int)HttpStatusCode.Forbidden);
 62                     LogHelper.WriteInfo(signInfo.PublicKey, signInfo.ApiName, ip, loginfo, (int)HttpStatusCode.Forbidden, message);
 63 
 64                     var response = new ResultResponse<object>();                    
 65 
 66                     response.Code = (int)HttpStatusCode.Forbidden;
 67                     response.Message = message;
 68                     response.Data = uri.Query;
 69                     return Task.Factory.StartNew<HttpResponseMessage>(() => { return request.CreateResponse(HttpStatusCode.Forbidden, response); });
 70                 }
 71             }
 72             else
 73             {
 74                 message = "无效请求";
 75                 //记录日志
 76                 string loginfo = string.Format("{0}  {1}  {2}  {3}", message, method, uri.ToString(), (int)HttpStatusCode.Forbidden);
 77                 LogHelper.WriteInfo(signInfo.PublicKey, signInfo.ApiName, ip, loginfo, (int)HttpStatusCode.Forbidden, message);
 78 
 79                 var response = new ResultResponse<object>();                
 80 
 81                 response.Code = (int)HttpStatusCode.Forbidden;
 82                 response.Message = message;
 83                 response.Data = uri.Query;
 84 
 85                 //return Task.Factory.StartNew<HttpResponseMessage>(() => { return new HttpResponseMessage(HttpStatusCode.Forbidden); });
 86                 return Task.Factory.StartNew<HttpResponseMessage>(() => { return request.CreateResponse(HttpStatusCode.Forbidden, response); });
 87             }
 88         }
 89 
125         //获取当前时间戳
126         private int GetCurrentTimestamp()
127         {
128             return Convert.ToInt32((DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds);
129         }
130         //获取接口名称
131         private string GetApiName(Uri uri)
132         {
133             return uri.LocalPath.TrimStart('/');
134         }        

282         /// <summary>
283         /// 签名信息类(用来生成签名)
284         /// </summary>
285         internal class SignInfo
286         {
287             /// <summary>
288             /// 请求方式
289             /// </summary>
290             public string Method { get; set; }
291             /// <summary>
292             /// 接口名称
293             /// </summary>
294             public string ApiName { get; set; }
295             /// <summary>
296             /// 接口各参数
297             /// </summary>
298             public string Params { get; set; }
299             /// <summary>
300             /// 公钥
301             /// </summary>
302             public string PublicKey { get; set; }
303             /// <summary>
304             /// 私钥
305             /// </summary>
306             public string PrivateKey { get; set; }
307             /// <summary>
308             /// 时间戳
309             /// </summary>
310             public int TimeStamp { get; set; }
311             /// <summary>
312             /// 签名字符串
313             /// </summary>
314             public string Sign { get; set; }
315         }
316         /// <summary>
317         /// 初始化签名信息类
318         /// </summary>
319         /// <param name="uri"></param>
320         /// <returns></returns>
321         private SignInfo InitSignInfo(HttpRequestBase requestBase)
322         {
323             SignInfo result = new SignInfo();
324 
325             NameValueCollection querycollection = null;
326 
327             try
328             {
329                 if (requestBase.HttpMethod == "POST")
330                 {
331                     querycollection = requestBase.Form;
332                 }
333                 if (requestBase.HttpMethod == "GET")
334                 {
335                     string querys = requestBase.Url.Query.TrimStart('?');
336                     StringBuilder querybuilder = new StringBuilder(querys);
337 
338                     querycollection = HttpUtility.ParseQueryString(querybuilder.ToString());
339                 }
340 
341                 result.ApiName = GetApiName(requestBase.Url);       //获取API名称            
342 
343                 var publickeylist = querycollection.AllKeys.Where(t => t.Equals("app_key", StringComparison.OrdinalIgnoreCase)).Select(key => querycollection[key].ToString());
344 
345                 result.PublicKey = publickeylist.First<string>();       //获取公钥
346 
347                 result.PrivateKey = GetPrivateKey(result.PublicKey);        //获取私钥
348 
349                 var timestamplist = querycollection.AllKeys.Where(t => t.Equals("time_stamp", StringComparison.OrdinalIgnoreCase)).Select(key => Convert.ToInt32(querycollection[key]));
350 
351                 result.TimeStamp = timestamplist.First<int>();      //获取时间戳
352 
353                 var signlist = querycollection.AllKeys.Where(t => t.Equals("sign", StringComparison.OrdinalIgnoreCase)).Select(key => querycollection[key].ToString());
354 
355                 result.Sign = signlist.First<string>();      //获取时间戳
356 
357                 //querycollection.Remove("app_key");
358                 //querycollection.Remove("time_stamp");
359                 //querycollection.Remove("sign");
360                 string param = "";
361                 foreach (string key in querycollection)
362                 {
363                     if (key.Equals("app_key", StringComparison.OrdinalIgnoreCase)
364                         || key.Equals("time_stamp", StringComparison.OrdinalIgnoreCase)
365                         || key.Equals("sign", StringComparison.OrdinalIgnoreCase))
366                     { continue; }
367                     param += string.Format("{0}={1}&", key, querycollection[key]);
368                 }
369                 result.Params = param.TrimEnd('&');     //获取接口各参数
370             }
371             catch (Exception ex)
372             {
373                 LogHelper.WriteException("初始化签名信息类失败!", ex);
374             }
375 
376             return result;
377         }
378 
379     }
380 }
 注意,代码中的关键部分我都进行了标红,并且我删掉了部分与示例无关的项目代码,你们重点看标红的部分代码应该就大概了解了那么现在,过滤器部分的逻辑已经算是写好了,等于是过滤器已经建好了,接下来,就是要把过滤器安装起来,怎么安装呢很简单,在App_Start文件夹下的WebApiConfig里面,加一句代码就可以了在WebApiConfig.cs里面的Register方法里加上一句config.MessageHandlers.Add(new Handler.CustomHandler()); 如下图这样一来,过滤器就算是装载好了,接下来,赶紧模拟请求断点调试试试效果吧

相关内容推荐