WebAPI中使用Autofac (过滤器的注册)

2023-10-27

第一步:在webAPI中安装 Autofac.WebApi2 。

不要错误的安装Autofac.Mvc5,也不要错误的安装Autofac.WebApi,因为Autofac.WebApi是给webapi1的,否则会报错:重写成员“Autofac.Integration.WebApi.AutofacWebApiDependencyResolver.BeginScope()”时违反了继承安全

第二步:在App_Start中创建一个类 :取名AutoFacConfig

第三步:引入 using Autofac;  using Autofac.Integration.WebApi;

namespace WebApi.App_Start
{
    public class AutoFacConfig
    {
        public static void InitAutoFac()
        {
            //得到你的HttpConfiguration.
            var configuration = GlobalConfiguration.Configuration;
            var builder = new ContainerBuilder();

            //注册控制器
            builder.RegisterApiControllers(Assembly.GetExecutingAssembly()).PropertiesAutowired();
            //可选:注册Autofac过滤器提供商.
            builder.RegisterWebApiFilterProvider(configuration);


            //builder.RegisterType(typeof(MyAuthenticationAttribute)).PropertiesAutowired(); //单独注册我们的MyAuthenticationAttribute过滤器
            var webapiAssembly = Assembly.Load("WebApi");

            //注册webapi项目中现实了IAuthorizationFilter接口或者实现了IActionFilter接口的非抽象过滤器类
            builder.RegisterAssemblyTypes(webapiAssembly).Where(r => !r.IsAbstract &&
            (typeof(IAuthorizationFilter).IsAssignableFrom(r)) || typeof(IActionFilter).IsAssignableFrom(r)).PropertiesAutowired();


            //对Repositorys这个程序集实现了IBaseRepository接口的非抽象类进行注册
            var repository = Assembly.Load("Repositorys");
            builder.RegisterAssemblyTypes(repository).Where(r => !r.IsAbstract).AsImplementedInterfaces().SingleInstance()
               .PropertiesAutowired();


            IContainer container = builder.Build();
            //将依赖关系解析器设置为Autofac。
            var resolver = new AutofacWebApiDependencyResolver(container);
            configuration.DependencyResolver = resolver;

        }
    }
}

第四步:在Global.asax中引用执行。

namespace WebApi
{
    public class WebApiApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            AutoFacConfig.InitAutoFac();//调用InitAutoFac()方法执行
            GlobalConfiguration.Configure(WebApiConfig.Register);
           
        }
    }
}

在过滤器中使用属性注入(特别注意过滤器的注册,过滤器对象最好不要直接new,而是去IOC容器中拿,否则不能直接在过滤器中使用属性注入)

例如:我创建了一个身份验证过滤器,如果过滤器中使用了属性依赖注入,那么注册这个过滤器的时候需要从IOC容器中去拿这个过滤器类对象的实例,不能直接new

namespace WebApi
{
    public class MyAuthenticationAttribute : IAuthorizationFilter//也可以直接继承AuthorizationFilterAttribute
    {
        public IAppInfosRepository app { get; set; }
        public bool AllowMultiple => true;

        public async Task<HttpResponseMessage> ExecuteAuthorizationFilterAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation)
        {
            //获得报文头中的AppKey和Sign (我们与客户端约定,在向服务端发起请求的时候,将AppKey和Sign放到请求报文头中)
            IEnumerable<string> appKeys;
            if (!actionContext.Request.Headers.TryGetValues("AppKey", out appKeys)) //从请求报文头中获取AppKey
            {
                {
                    return new HttpResponseMessage(System.Net.HttpStatusCode.Unauthorized) { Content = new StringContent("报文头中的AppKey为空") };
                }
            }
            IEnumerable<string> signs;
            if (!actionContext.Request.Headers.TryGetValues("Sign", out signs)) //从请求报文头中获取Sign
            {
                return new HttpResponseMessage(System.Net.HttpStatusCode.Unauthorized) { Content = new StringContent("报文头中的Sign为空") };
            }
            string appKey = appKeys.First();
            string sign = signs.First();
            var appInfo = await app.GetByAppKeyAsync(appKey);//从数据库获取appinfo这条数据(获取AppKey,AppSecret信息)
            if (appInfo == null)
            {
                return new HttpResponseMessage(System.Net.HttpStatusCode.Unauthorized) { Content = new StringContent("不存在的AppKey") };
            }
            if (appInfo.IsEnable == "true")
            {
                return new HttpResponseMessage(System.Net.HttpStatusCode.Forbidden) { Content = new StringContent("AppKey已经被封禁") };
            }

            string requestDataStr = ""; //请求参数字符串
            List<KeyValuePair<string, string>> requestDataList = new List<KeyValuePair<string, string>>();//请求参数键值对
            if (actionContext.Request.Method == HttpMethod.Post) //如果是Post请求
            {
                //获取Post请求数据  
                requestDataStr = GetRequestValues(actionContext);
                if (requestDataStr.Length > 0)
                {
                    string[] requestParamsKv = requestDataStr.Split('&');
                    foreach (var item in requestParamsKv)
                    {
                        string[] pkv = item.Split('=');
                        requestDataList.Add(new KeyValuePair<string, string>(pkv[0], pkv[1]));
                    }
                    //requestDataList就是按照key(参数的名字)进行排序的请求参数集合   
                    requestDataList = requestDataList.OrderBy(kv => kv.Key).ToList();
                    var segments = requestDataList.Select(kv => kv.Key + "=" + kv.Value);//拼接key=value的数组
                    requestDataStr = string.Join("&", segments);//用&符号拼接起来
                }

            }
            if (actionContext.Request.Method == HttpMethod.Get) //如果是Get请求
            {
                //requestDataList就是按照key(参数的名字)进行排序的请求参数集合          
                requestDataList = actionContext.Request.GetQueryNameValuePairs().OrderBy(kv => kv.Key).ToList();
                var segments = requestDataList.Select(kv => kv.Key + "=" + kv.Value);//拼接key=value的数组
                requestDataStr = string.Join("&", segments);//用&符号拼接起来
            }

            //计算Sign (即:计算requestDataStr+AppSecret的md5值)
            string computedSign = MD5Helper.ComputeMd5(requestDataStr + appInfo.AppSecret);

            //用户传进来md5值和计算出来的比对一下,就知道数据是否有被篡改过
            if (sign.Equals(computedSign, StringComparison.CurrentCultureIgnoreCase))
            {
                return await continuation();
            }
            else
            {
                return new HttpResponseMessage(System.Net.HttpStatusCode.Unauthorized) { Content = new StringContent("sign验证失败") };
            }
        }


        /// <summary>
        /// 获取Post请求的请求参数内容
        /// 参考资料:https://www.cnblogs.com/hnsongbiao/p/7039666.html
        /// </summary>
        /// <param name="actionContext"></param>
        /// <returns></returns>
        public string GetRequestValues(HttpActionContext actionContext)
        {
            Stream stream = actionContext.Request.Content.ReadAsStreamAsync().Result;
            Encoding encoding = Encoding.UTF8;
            /*
                这个StreamReader不能关闭,也不能dispose, 关了就傻逼了
                因为你关掉后,后面的管道  或拦截器就没办法读取了
                所有这里不要用using
                using (StreamReader reader = new StreamReader(stream, System.Text.Encoding.UTF8))
                {
                    result = reader.ReadToEnd().ToString();
                }
            */
            var reader = new StreamReader(stream, encoding);
            string result = reader.ReadToEnd();
            /*
            这里也要注意:   stream.Position = 0;
            当你读取完之后必须把stream的位置设为开始
            因为request和response读取完以后Position到最后一个位置,交给下一个方法处理的时候就会读不到内容了。
            */
            stream.Position = 0;
            return result;
        }
    }
}

在WebApiConfig.cs类中注册这个过滤器 (统一注册过滤器)

namespace WebApi
{
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            // Web API 配置和服务

            // Web API 路由
            config.MapHttpAttributeRoutes();

            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );


            //从Autofac的IOC容器中拿到MyAuthenticationAttribute过滤器的类对象
            //MyAuthenticationAttribute authorFilter = (MyAuthenticationAttribute)GlobalConfiguration.Configuration.DependencyResolver.GetService(typeof(MyAuthenticationAttribute));
            //config.Filters.Add(authorFilter); //注册过滤器

            //注意:如果想在过滤器中使用属性注入,则注册这个过滤器的时候,这个过滤器的对象必须要用IOC容器过得到            
            //不能直接new 例如:不能直接config.Filters.Add(new MyAuthenticationAttribute())
            //因为一个对象必须是由IOC容器创建出来的,IOC容器才会自动帮我们注入


            #region 统一注册过滤器
            var webapiAss = Assembly.Load("WebApi");
            //从webapiAss中拿到所有实现了IAuthorizationFilter接口,或者实现了IActionFilter接口的非抽象过滤器类
            var filters = webapiAss.GetTypes().Where(r => !r.IsAbstract && (typeof(IAuthorizationFilter).IsAssignableFrom(r) || typeof(IActionFilter).IsAssignableFrom(r)));
            foreach (var item in filters)
            {
                //从IOC容器中拿到过滤器类对象(因为过滤器都是实现了IFilter接口的,所有这里以IFilter接口来接收)
                IFilter filter = (IFilter)GlobalConfiguration.Configuration.DependencyResolver.GetService(item);
                config.Filters.Add(filter); //注册过滤器
            } 
            #endregion
        }
    }
}


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

WebAPI中使用Autofac (过滤器的注册) 的相关文章

随机推荐

  • Raspberry Pi Pico使用MicroPython---(4)

    这一次我们使用Raspberry pi pico点亮ST7735驱动的1 8寸RGB的TFT屏幕 网络的资料比较少 通过bing com能查到使用Arduino写的例程 这里我们还是采用熟悉的Micropython编程 这里主要参考的是 G
  • python 文件查找性能对比 python与powershell

    目录 6万行的文本文件 python遍历查找和powerchell 查找方式对比 代码 结论
  • 【计算机网络】网络数据传输流程详解

    目录 1 基础知识 1 1 IP地址 1 2 子网掩码 1 3 MAC地址 1 4 网络传输遇到的设备 1 4 1 集线器 1 4 2 交换机 1 4 3 主机 1 4 5 路由器 1 5 冲突域 1 6 广播域 2 局域网数据传输流程 2
  • PandoraBox 挂载不上摄像头,求大佬指导!

    PandoraBox 挂载不上摄像头 求大佬指导 安装好驱动 以及mjpg streamer Base on LEDE OpenWrt 19 09 r5054 2019 09 07 git b7ad7d224 更新一下 root Pando
  • Vue - 项目中使用iconfont(阿里图标库)

    项目中如何使用iconfont 阿里图标库 一 登陆iconfont官网 https www iconfont cn 二 创建一个图标项目 1 点击 图标管理 子目录中的子目录 我的项目 进入个人图标项目 2 点击创建一个图标项目 三 将需
  • 走进包装类

    引入 Java认为一切皆对象 引用数据类型就是对象 但是在Java中8中基本数据类型不是对象 只是表示一种数据的类型形式 Java为了一切皆对象的思想统一 把8中基本数据类型转换成对应的类 这个类称为基本数据类型的包装类 基本数据类型 包装
  • vue运行后没有显示内容

    运行成功没有报错但是就是不显示内容 进浏览器看到控制台的报错信息 vue runtime esm js c320 4573 Vue warn Property or method yzmStr is not defined on the i
  • 如何使用cookie信息,完成自动登录

    在做爬虫任务的时候 我们常常会遇到很多网页必须登录后 才可以开放某些页面 所以登录是爬取网页的第一步 但是 通过post表单 包含用户名和密码 的方法 对于那些不需要输入比较复杂的验证码的网页 可以使用正则表达式将验证码和验证码的ID匹配得
  • MMEditing环境配置

    MMEditing环境配置 MMEditing is an open source image and video editing toolbox based on PyTorch It is a part of the OpenMMLab
  • ZynqMP Petalinux2021.1设置工程离线编译

    前言 Ubuntu18 04安装Petalinux 2021 1 sudaroot的博客 CSDN博客 介绍 PetaLinux基于Yocto 每次创建或者编译工程下载都需要联网下载工程所需文件 且下载的文件非常庞大 这就导致编译速度还受网
  • 《Python量化投资》01 量化投资之单因子测试(概述,Pandas的适用)

    一 股票aplha多因子策略介绍 量化投资是指通过数量化方式及计算机程序化发出买卖指令 以获取稳定收益为目的的交易方式 在海外的发展已有30多年的历史 其投资业绩稳定 市场规模和份额不断扩大 得到了越来越多投资者认可 从全球市场的参与主体来
  • C#简单操作MongoDB

    新建一个窗体程序 使用Nuget安装mongodb driver 或者直接引用dll如下 代码 using System using System Collections Generic using System ComponentMode
  • Shader编程学习笔记(二)—— Shader和渲染管线

    http www cnblogs com maple share p 5395097 html Shader和渲染管线 什么是Shader Shader 中文翻译即着色器 是一种较为短小的程序片段 用于告诉图形硬件如何计算和输出图像 过去由
  • i2c

    I2C是由Philips公司发明的一种串行数据通信协议 仅使用两根信号线 SerialClock 简称SCL 和SerialData 简称SDA I2C是总线结构 1个Master 1个或多个Slave 各Slave设备以7位地址区分 地址
  • 使用Python3解压gz、tar、tgz、zip、rar五种格式的压缩文件例子

    使用Python3解压如下五种压缩文件 gz tar tgz zip rar 简介 gz 即gzip 通常只能压缩一个文件 与tar结合起来就可以实现先打包 再压缩 tar linux系统下的打包工具 只打包 不压缩 tgz 即tar gz
  • Chrome-网页另存为单个网页文件后,单个网页文件无法正常显示的问题

    通过Chrome浏览器另存单个网页文件 再次打开出现时出现下图效果 将存储的单个网页文件的扩展名由html修改为mhtml即解决该问题
  • 数据库的可伸缩性的探索

    数据库的可伸缩性的探索 Author skate Time 2009 5 30 数据库在当今社会越来越重要 尤其对于一个发展迅速的企业 其数据是爆炸式的发展 为了适应其数据的发展 对数据库的架构体系设计要求也越来越高 它要可以方便的线形扩展
  • Windows 安装pdf2image运行后遇到PDFInfoNotInstalledError解决办法

    最近在学习图像处理 需要安装pdf2image 安装没有报错 运行之后报错 pdf2image exceptions PDFInfoNotInstalledError Unable to get page count Is poppler
  • UE4_运行模式下(Runtime)样条曲线(Spline)新增Point导致Length变长

    Spline 在运行模式下新增一个point引发的问题 问题描述 在Spline曲线之间增加一个Point 导致Spline的Length变长 产生的原因 Spline 之前本身具有2个Point 博主想通过鼠标点击的方式在曲线之间产生一个
  • WebAPI中使用Autofac (过滤器的注册)

    第一步 在webAPI中安装 Autofac WebApi2 不要错误的安装Autofac Mvc5 也不要错误的安装Autofac WebApi 因为Autofac WebApi是给webapi1的 否则会报错 重写成员 Autofac