1、WebAPI的工做方式web
WebAPI的工做方式:HTTP的请求最早是被传递到HOST中的,若是WebAPI是被寄宿在IIS上的,这个HOST就是IIS上,HOST是没有能力也没有必 要进行请求的处理的,请求经过HOST被转发给了HttPServer此时已经进入WebAPI的处理加工范围,HttpServer是 System.Net.HTTP中的一个类,经过HttpServer,请求被封装成了WebAPI中的请求承载 类:HttpRequestMessage,这个封装后的请求能够通过一系列自定义的Handler来处理,这些handler串联成一个 pipeline,最后请求会被传递给HttpControlDispather,这个类经过对路由表的检索来肯定请求将被转发到的具体的 Controller中的Action。api
由此咱们早就能够看出,想要解决第二个问题,能够直接在Handler PipeLine中进行,这种AOP风格的过滤器(拦截器)在REST的Webservice的安全验证中应用很广,通常你们比较乐于在HTTP头或者在 HTTP请求的URL中加上身份验证字段进行身份验证,下面举一个在Http头中添加身份验证信息的小例子:安全
2、说明服务器
本节所使用的例子,只是在“asp.net mvc4 webapi之应用客户端访问服务器端”的例子上稍做修改而已,在看本篇文章以前,请先看文档“asp.net mvc4 webapi之应用客户端访问服务器端” mvc
3、例子修改asp.net
首先打开文档“webapi之应用客户端访问服务器端.docx”中对应的解决方案“MyTest”,下面分别介绍咱们对服务器端、客户端所作的修改ide
一、服务器端url
(1)、首先添加一个文件夹,命名为:HandlerLibspa
(2)、在文件夹HandlerLib添加一个类,并命名为:SecurityHandler,代码以下.net
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using System.Web;
namespace MyServer.HandlerLib
{
public class SecurityHandler : DelegatingHandler
{
protected override System.Threading.Tasks.Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken
cancellationToken)
{
int matchHeaderCount = request.Headers.Count((item) =>
{
if ("keyword".Equals(item.Key))
{
foreach (var str in item.Value)
{
//wanli就是约定的服务器端验证口令或验证验证信息
if ("wanli".Equals(str))
{
return true;
}
}
}
return false;
});
if (matchHeaderCount > 0)
{
return base.SendAsync(request, cancellationToken);
}
return Task.Factory.StartNew<HttpResponseMessage>(() => { return new HttpResponseMessage(HttpStatusCode.Forbidden); });
}
}
}
(3)、添加
注:代码的处理逻辑很简单:若是身份验证码匹配成功,则经过base.SendAsync继续将请求向下传递,不然返回直接中断请求的传递,直接返回一个响应码为403的响应,指示没有权限。
注意因为SendAsync的返回值须要封装在Task之中,因此须要使用Task.Factory.StartNew将返回值包含在Task中
将SecurityHandler注入到HOST中
本例中WebAPI HOST在IIS上,因此咱们只需将咱们定义的SecurityHandler在Application_Start中定义便可
protected void Application_Start()
{
//省略其余逻辑代码
GlobalConfiguration.Configuration.MessageHandlers.Add(new SecurityHandler ());
}
因为WebAPI Host在IIS上,因此HttpServer和HttpControllerDispatcher不用咱们手工处理
二、客户端的修改
添加类RequestCheckHandler.cs,其代码以下:
客户端的RequestCheckHandler用于将身份验证信息添加入报头
class RequestCheckHandler : DelegatingHandler
{
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
{
request.Headers.Add("keyword", "wanli");
return base.SendAsync(request, cancellationToken);
}
}
注:
1. RequestCheckHandler继承自DelegatingHandler类,上面已经说过,WebAPI的客户端和服务端被设计为相互对应的两套结构,因此不管是在客户端仍是服务端,RequestCheckHandler都是继承自DelegatingHandler类
2.DelegatingHandler的sendAsync方法即是处理请求和接受请求时会被调用的方法,该方法返回值是HttPResponseMessage,接收的值为HttpRequestMessage,符合咱们的通常认知
3.方法的最后,调用base.SendAsync是将Request继续向该pipeline的其余RequestCheckHandler传递,并获取其返回值。因为该方法不包含Response的处理逻辑,只需直接将上一个RequestCheckHandler的返回值直接返回
客户端的form1.cs窗体的后台代码修改成
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace MyClient
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void btnSubmit_Click(object sender, EventArgs e)
{
string userName = txName.Text.Trim();
string passWord = txPwd.Text.Trim();
string url = @"http://localhost:8748/api/User/GetUserInfo?userName=" + userName + "&passWord="+passWord;
HttpClient client = new HttpClient(new RequestCheckHandler() { InnerHandler = new HttpClientHandler() });
HttpResponseMessage response = client.GetAsync(url).Result;
string str= response.Content.ReadAsStringAsync().Result;
MessageBox.Show(str);
}
}
}
客户端的主程序建立了一个HttpClient,HttpClient能够接受一个参数,该参数就是CustomHandler,此处咱们嵌入了咱们定义的 RequestUpHandler,用于对Request报头进行嵌入身份验证码的处理,CustomHandler经过InnerHandler属性嵌 入其内置的下一个CustomHandler,此处,因为没有下一个CustomerHandler,咱们直接嵌入HttpClientHandler用 于将HttpRequestMessage转化为HTTP 请求、将HTTP响应转化为HttpResponseMessage