zoukankan      html  css  js  c++  java
  • 在web api中进行统一安全验证类DelegatingHandler ,

    根据web api 官方参考文献 总结出一下代码举例:

    将 HTTP 响应消息的处理委托给另一处理程序(称为“内部处理程序”)的 HTTP 处理程序的类型。

    如何理解这句话的意思?

    首先我们应知道Asp.Net Web Api 的http消息响应机制,这里我可以解释为:消息管道串联。官方代码指出:public abstract class DelegatingHandler : System.Net.Http.HttpMessageHandler,

    而具体实现“管道串联”是通过DelegatingHandler这个类型来完成。

    通过以上文档得出疑问

    当DelegatingHandler自己负责的消息处理任务完成之后可以委托另一个HttpMessagHandler进行后续的处理。

    如果这个被委托的也是一个DelegatingHandler对象,不就可以组成一个委托链了吗?而这个委托链不就是由一个个DelegatingHandler组成的消息处理管道吗?

     以上问题我们可以从程序集 System.Net.Http.dll, v4.0.0.0中得到答案:
    namespace System.Net.Http
    {
        // 摘要: 
        //     被称为内部处理程序的并将 HTTP 响应消息委托给另一处理程序的 HTTP 处理程序的基类型。
        public abstract class DelegatingHandler : HttpMessageHandler
        {
            // 摘要: 
            //     创建 System.Net.Http.DelegatingHandler 类的新实例。
            protected DelegatingHandler();
            //
            // 摘要: 
            //     创建特定内部处理程序的 System.Net.Http.DelegatingHandler 类的新实例。
            //
            // 参数: 
            //   innerHandler:
            //     负责处理 HTTP 响应消息的内部处理程序。
            protected DelegatingHandler(HttpMessageHandler innerHandler);
    
            // 摘要: 
            //     获取或设置处理 HTTP 响应消息的内部处理程序。
            //
            // 返回结果: 
            //     返回 System.Net.Http.HttpMessageHandler。 HTTP 响应消息的内部处理程序。
            public HttpMessageHandler InnerHandler { get; set; }
    
            // 摘要: 
            //     释放由 System.Net.Http.DelegatingHandler 使用的非托管资源,并可根据需要释放托管资源。
            //
            // 参数: 
            //   disposing:
            //     如果为 true,则释放托管资源和非托管资源;如果为 false,则仅释放非托管资源。
            protected override void Dispose(bool disposing);
            //
            // 摘要: 
            //     以异步操作发送 HTTP 请求到内部管理器以发送到服务器。
            //
            // 参数: 
            //   request:
            //     要发送到服务器的 HTTP 请求消息。
            //
            //   cancellationToken:
            //     取消操作的取消标记。
            //
            // 返回结果: 
            //     返回 System.Threading.Tasks.Task<TResult>。 表示异步操作的任务对象。
            //
            // 异常: 
            //   System.ArgumentNullException:
            //     request 为 null。
            protected internal override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken);
        }
    }

    我们在此可以总结出,如ASP.NET Web API的消息处理管道均由DelegatingHandler组成(位于管道尾端的HttpMessageHandler除外),我们就可以根据其InnerHandler获得对被委托的HttpMessageHandler对象的引用,由此便构成消息处理的链式结构。组成ASP.NET Web API核心框架的消息处理管道,

    理论总结的差不多,那么下面我们就对该消息处理委托类进行消息自定义操作,

    public class RequestMessageDelegatingHandler : DelegatingHandler
        {
            protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
            {
                return base.SendAsync(request, cancellationToken).ContinueWith((responseToCompleteTask) =>
                {
                    //获取URL参数
                    NameValueCollection query = HttpUtility.ParseQueryString(request.RequestUri.Query);
                    //获取Post正文数据,比如json文本
                    string fRequesContent = request.Content.ReadAsStringAsync().Result;
    
                    //可以做一些其他安全验证工作,比如Token验证,签名验证。
                    //可以在需要时自定义HTTP响应消息
                    //return SendError("自定义的HTTP响应消息", HttpStatusCode.OK);
    
    
                    HttpResponseMessage response = responseToCompleteTask.Result;
                    HttpError error = null;
                    if (response.TryGetContentValue<HttpError>(out error))
                    {
                        //添加自定义错误处理
                        //error.Message = "请求失败";
                    }
    
                    if (error != null)
                    {
                        //记录关键的异常信息
                        QWPlatform.SystemLibrary.LogManager.Logger.Instance.Error("[" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "]404错误:请求数据" + error.Message);
                        //返回错误信息
                        throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.OK)
                        {
                            //封装处理异常信息,返回指定JSON对象
                            Content = new StringContent(new ZLSoft.CHSS.Web.Public.Library.BaseClass.AjaxResult(Common.Base.AjaxResultType.失败, error.Message + "404").CreateResultString()), //Encoding.GetEncoding("UTF-8"), "application/json"
                            ReasonPhrase = "Exception"
    
                        });
                    }
                    else
                    {
                        return response;
                    }
                }, cancellationToken);
            }
        }

    接下来,我们只需要把当前类注册到 webapiconfig类当中。

    public class WebAPIConfig
        {
            public static void Register(HttpConfiguration config)
            {
                //跨域配置
                config.EnableCors(new EnableCorsAttribute("*", "*", "*"));
                //  config.MapHttpAttributeRoutes();
    
                //注册路由映射
                config.Routes.MapHttpRoute(
                    name: "DefaultApi",
                    routeTemplate: "api/{controller}/{action}/{id}",
                    defaults: new { id = RouteParameter.Optional }
                    );
                config.MessageHandlers.Add(new RequestMessageDelegatingHandler()); 
    } }

    接下里就可以在 RequestMessageDelegatingHandler 中间写好消息处理机制哪里进行统一的安全校验。

  • 相关阅读:
    JBPM使用
    eclipse spring3.X redis 整合-配置
    30分钟学会如何使用Shiro
    Linux下环境变量配置方法梳理(.bash_profile和.bashrc的区别)
    Eclipse上Maven环境配置使用 (全)
    redis未设置idle超时时间导致连接过多
    linux下搭建redis并解决无法连接redis的问题
    redis配置用户认证密码
    spring配置redis
    Linux nohup和&后台运行,进程查看及终止,进程信息输出,控制台信息输出
  • 原文地址:https://www.cnblogs.com/lwyu/p/10593727.html
Copyright © 2011-2022 走看看