第一步:在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);
}
}
}
例如:我创建了一个身份验证过滤器,如果过滤器中使用了属性依赖注入,那么注册这个过滤器的时候需要从IOC容器中去拿这个过滤器类对象的实例,不能直接new
namespace WebApi
{
public class MyAuthenticationAttribute : IAuthorizationFilter//也可以直接继承AuthorizationFilterAttribute
{
public IAppInfosRepository app { get; set; }
public bool AllowMultiple => true;
public async Task ExecuteAuthorizationFilterAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func> continuation)
{
//获得报文头中的AppKey和Sign (我们与客户端约定,在向服务端发起请求的时候,将AppKey和Sign放到请求报文头中)
IEnumerable appKeys;
if (!actionContext.Request.Headers.TryGetValues("AppKey", out appKeys)) //从请求报文头中获取AppKey
{
{
return new HttpResponseMessage(System.Net.HttpStatusCode.Unauthorized) { Content = new StringContent("报文头中的AppKey为空") };
}
}
IEnumerable 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> requestDataList = new List>();//请求参数键值对
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(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验证失败") };
}
}
///
/// 获取Post请求的请求参数内容
/// 参考资料:https://www.cnblogs.com/hnsongbiao/p/7039666.html
///
///
///
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
}
}
}