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