Host ASP.NET WebApi in Owin

來源:互聯網
上載者:User

標籤:uil   foreach   img   調用順序   html   其他   span   文檔   pac   

什麼是OWIN                                          

  Owin其實是微軟為瞭解耦.Net Web app對IIS的依賴而制定的一套規範,規範定義了Web Server與Web App之間的介面,這樣Web App就可以Host在所有相容OWIN規範的Web Server了(包含控制台應用和Windows服務...)。具體來說,Owin將Web app和Web Server整體劃分為以下幾個模組。

 

Host 

根據官方解釋,Host是指server和application所依託執行的進程。主要負責應用的啟動與配置。

Server

Server負責直接與用戶端進行Http通訊,然後將請求轉換為Owin的語義,然後用Owin的流程進行處理的Http Server.

Middleware

Middleware是開發人員自行註冊到Owin處理請求管道中的模組(類似IIS中的Module),可以直接參与請求的處理。所以我認為Web Api架構其實也屬於Middleware.(不過官方將Web Api架構歸屬於Web Framework。它會將Owin的語義轉換為Web Framework內部的語義,然後按照內部的處理流程處理請求)

Application

Application就是基於所有上面所有Middleware(準確說應該是Web Framework,看來官方定義一個Web Framework模組是有意義的)所構建的應用程式層。

這些定義只是一些描述,那具體實施是怎麼實施呢。微軟自己有一個開源項目叫Katana,它是對Owin規範的官方實現(其實主要就是實現上述的Host/Server部分,因為Middleware,Application部分都是需要我們自己開發的)。下面通過使用Katana,我們將web api部署在一個控制台進程中,來看看具體怎麼去使用它以及OWIN介面到底是什麼。

Host WebApi in Console App                                  

1.首先我們建立一個控制台應用

2.然後我們通過Nuget引入Package Microsoft.AspNet.WebApi.OwinSelfHost,安裝過程中所有依賴的Owin和Web Api的package都會一併安裝。

3.我們可以添加一個ApiController:PersonController,並添加一個介面方法:

 1 [RoutePrefix("api/persons")] 2     public class PersonController : ApiController 3     { 4         [Route("{id}/name")] 6         public string getName(string id) 7         { 8             return id + "@boss"; 9         }10     }

4. 接下來我們需要將web api進行配置和部署。該Katana登場了。

首先按照Owin約定我們得添加一個用於Startup的類,這個類中需要有一個簽名為Configuration(IAppBuilder app)的方法:

public class Startup{        public void Configuration(IAppBuilder appBuilder)        {var configuration = new HttpConfiguration();            configuration.MapHttpAttributeRoutes();//配置web api的router            appBuilder.UseWebApi(configuration);//這個擴充是由package Microsoft.AspNet.WebApi.Owin提供,它負責註冊web api到owin的處理管道中,
                            //並在處理請求時將Owin語義與web api中的語義進行轉換 }}

我們在Main函數中添加如下代碼:

WebApp.Start<Startup>("http://localhost:8088/");//WebApp利用katana實現的OwinHttpListener來在指定url上監聽http請求。Console.WriteLine("Started!");Console.ReadKey();

這樣我們就基於katana實現了在console app中運行web api了。

F5運行以下,看看效果。

然後可以通過瀏覽器訪問http://localhost:8088/api/persons/123/name,應該能看到如下畫面

Add Authenticate Middleware                           

接下來我們通過添加owin middleware的方式來為web api添加保護機制(Authentication)。在這之前我先解釋下關於Middleware的基礎知識。

Middleware是一組Owin server在處理http請求的時候會輪流調用到的模組,他們通過調用IAppBuilder的Use擴充方法來註冊。運行時的Middleware的調用順序與註冊順序一致。

並且對管道中下一Middleware的調用是由當前執行的Middleware來執行。具體到介面來說是這樣:

1. OWIN定義了一個Middleware的執行介面Func<IDictionary<string,object>,Task>,然後要求每個Middleware的定義需滿足如下條件:

  •     提供接受一個類型為執行介面類型(Func<IDictionary<string,object>,Task>)的建構函式
  •  提供一個滿足如下籤名的方法Task Invoke(IDictionary<string,object> parameters)

也就是說,owin將每個middleware最後都抽象成了一個函數,這個函數接受IDictionary作為參數,返回一個執行具體處理的Task.

2. OWIN在建立每個Middleware的執行個體時,會根據註冊順序傳入當前Middleware在執行管道中的下一個Middleware的執行介面。Middleware需要儲存起來後續調用。

3. 當處理請求時,Server會調用管道中第一個Middleware的Invoke方法,然後由該Middleware決定處理完請求後是否調用下一個Middleware. 在調用Invoke時,Owin server

會將當前請求的所有內容屬性傳入該Dictionary對象中。詳細的內容屬性列表見官方文檔。

我們在當前項目中建立AuthenticateMiddleWare,代碼如下:

public class AuthenticateMiddleware{        private Func<IDictionary<string, object>, Task> nextAppFunc;        public AuthenticateMiddleware(Func<IDictionary<string, object>, Task> nextMiddleWareFunc)        {            nextAppFunc = nextMiddleWareFunc;        }        public async Task Invoke(IDictionary<string, object> parameters)        {            Console.WriteLine("Authenticating");            string queryString = parameters["owin.RequestQueryString"] as string;//擷取http請求的query string            var respStream = parameters["owin.ResponseBody"] as Stream;//擷取http請求的response stream            var streamWriter = new StreamWriter(respStream);            var queryDic = ParseQueryString(queryString);            const string tokenKey = "token";            const string predefineToken = "88888888";            if (!queryDic.ContainsKey(tokenKey)||queryDic[tokenKey]!=predefineToken)//檢查請求中所帶token是否合法,此處僅為測試需要,直接寫入程式碼。            {
         //如果token非法,則直接寫入Access Denied到response中。停止繼續執行管道中其他middleware. streamWriter.WriteLine("Access Denied!"); streamWriter.Flush(); return; }
       var identity = new GenericIdentity("boss zhang"); parameters["server.User"] = new GenericPrincipal(identity, new string[] { "admin" });//token合法,產生principal對象到parameters中,key "server.User"
                                                        //用於儲存當前請求的user資訊,相當於HttpContext.User if (nextAppFunc != null) { await nextAppFunc.Invoke(parameters);//繼續執行管道中下一個middleware } } private Dictionary<string, string> ParseQueryString(string originalString) { string[] queryStringItems = originalString.Split(new string[] { "&" }, StringSplitOptions.RemoveEmptyEntries); var queryStringDic = new Dictionary<string, string>(); foreach (var item in queryStringItems) { string[] queryStringKvp = item.Split(new string[] { "=" }, StringSplitOptions.None); if (queryStringKvp.Length == 2) { queryStringDic[queryStringKvp[0]] = queryStringKvp[1]; } } return queryStringDic; }
}

然後再給之前定義的PersonController加上Authorize Attribute加以保護。

F5運行,然後在瀏覽器中訪問以下url: http://localhost:8088/api/persons/123/name?token=88888888.依然能得到之前正確的返回。

如果去掉token=88888888,則得到如下結果。

這說明我們的AuthenticateMiddle發揮作用了。

 完整代碼見https://github.com/lbwxly/OwinSample.git

參考文檔:

http://www.dotnetcurry.com/signalr/915/owin-katana-signalr-web-server

https://ovaismehboob.com/2014/12/01/understanding-owin-by-developing-a-custom-owin-middleware-component/

Host ASP.NET WebApi in Owin

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.