1. 程式人生 > >快速入門系列--WebAPI--01基礎

快速入門系列--WebAPI--01基礎

簡單例子 codec 應該 sem ons 請求重定向 選擇 char 阻止

ASP.NET MVC和WebAPI已經是.NET Web部分的主流,剛開始時兩個公用同一個管道,之後為了更加的輕量化(WebAPI是對WCF Restful的輕量化),WebAPI使用了新的管道,因此兩者相關類的命名空間有細微差異,在使用時需要註意。

WebAPI學習系列目錄如下,歡迎您的閱讀!

快速入門系列--WebAPI--01基礎

快速入門系列--WebAPI--02進階

快速入門系列--WebAPI--03框架你值得擁有

快速入門系列--WebAPI--04在老版本MVC4下的調整

技術分享

  • WebAPI與ASP.NET路由的異同

ASP.NET MVC的路由:Routes(RouteCollection)的線程安全,讀寫鎖,GetReadLock, GetWriteLock。RouteTable.Routes.MapPageRoute(…);

命名空間為System.Web.Routing中

WebAPI的路由:首先介紹其相關類型,他們均是對Http報文的簡易封裝,System.Net.Http(HttpRequestMessage, HttpResponseMessage)。

命名空間為System.Web.Http.Routing中

兩個路由的銜接,例如在Web Host模式中將WebAPI寄宿於一個Web應用時,其最終的URL路由還是通過ASP.NET本身的路由系統完成,幾個主要的類型,HttpControllerRouteHandler,

HttpRouteHandler。

  • 消息處理管道

還記的ASP.NET MVC中的核心是HttpHandler,而在WebAPI中其管道處理器是HttpMessageHandler。在實際中其通過職責鏈模式將委托通過InnerHandler(DelegationHandler)方式進行處理。其中,其中這個管道最開始的是httpServer,最末端的是HttpRoutingDispatcher(均在System.Web.Http命名空間下,支持異步模型),P108

技術分享

Tip:額外想想也能理解WebAPI管道為什麽更加輕量化,因而它只需要處理Json等類型數據,不需要考慮如頁面、JS、靜態資源等內容。

  • 常見特性

Class: [RoutePrefix("api/demo")],針對具體類的路由設置,相對RouteConfig,粒度更細。

Method: [Route("action")]

[HttpGet], [HttpPost]

關於Web服務,其中比較難的概念一般都集中在安全,其相關概念非常的多,包括Windows相關認證模式、Forms認證、第三方認證、跨域訪問等,接下來一一介紹。此外還會附加HttpClient、IOC框架的選擇、服務冪等性、SignalR、EntLib中的EHAB等概念。

技術分享

.NET安全模型:

Identiy表示用戶身份, Identity AuthenticationType, IsAuthenticated, Name},常見的Identity有WindowsIdentity, FormsIdentity, GenericIdentity。P556

IPrincipal, 被成功實施授權的實體,等價於身份加角色,包括WindowsPrincipal(windows的權限組),GenericPrincipal, RolePrincipal(Membership組件和Roles組件) 。常見的認證方式通過"質詢-應答"(challenge-Response)方式。

常見http認證方式,Basic和Digest,前者使用將認證憑證(用戶名+密碼)通過base64編碼而未加密,但我們可以使用https傳輸來解決機密性問題。與此相關的兩個過濾器, AuthenticationFilter和AuthorizationFilter。

補充ActionFilter概念,比如請求涉及大量運算,並且輸入和輸出一一對應(即相同的輸入有相同的輸出),那麽可以考慮緩存Action。P585

Windows認證模式(均通過在IIS中設置身份認證模式)

WebHost寄宿下的安全:Windows認證模式,通過Basic, Digest認證方案,最終采用NTLM或者Kerberos協議。認證用戶的Principal體現在HttpContext、當前線程、ApiControlelr。Keep-Alive,Fidder查看調用。

名稱 狀態 響應類型
Active Directory客戶端證書身份驗證 已禁用 HTTP 401 質詢
ASP.NET 模式 已禁用
Forms身份驗證 已禁用 HTTP 302 登錄/重定向
Windows身份驗證 已禁用 HTTP 401 質詢
基本身份驗證(Windows/Basic) 已禁用 HTTP 401 質詢
匿名身份驗證 已禁用
摘要式身份驗證(Windows/digest) 已啟用 HTTP 401 質詢
  • Basic認證

現在都是HTTP401 質詢模型,只有forms是http 302 登錄/重定向。這個關於basic的質詢方式很有意思,就是當你請求時,出現http 401,會要求你輸入用戶名密碼,輸入後你輸入的用戶名和密碼會被base64編碼發送的服務器,形式是Basic YWRtaW46YWRtaW4=,這部分的head就是authentication。查看windows的憑據管理器,賬號密碼木有問題,但仍然不能通過驗證,非常的傷感,自己試著加上域cn1\,結果OK了,感覺棒棒噠,哈哈,說明asp.net安全模型和windows有很好的整合性。

Basic模式的流程是,瀏覽器向服務器IIS以匿名的方式發送GET請求,IIS回復一個401 Unauthorized的響應,該響應用"www-authenticate"報頭告訴客戶端采用的認證方案(basic)和對應的領域(Realm, localhost)。瀏覽器收到響應彈出登錄對話框,收集輸入的賬號密碼組成字符串作為認證憑證,接下來,瀏覽器再次發送請求,在authorization包頭中攜帶認證的方案和用戶的憑證Basic YWRtaW46YWRtaW4=,IIS解密後認證,action順利執行。

Base64:是網絡常見的用於傳輸8bit字節代碼的編碼方式,用在http表單(包括隱藏的表單域)和http GET url中,base64編碼的信息具有不可讀性,但不具有機密性,使用時需要註意應用場景。

  • Digest認證

Digest認證僅僅適用於Domain模式,如果基於WorkGroup模式,也無法使用,接下來通過fiddler看看相應的HTTP消息頭。

HTTP 401的響應:

WWW-Authenticate: Digest qop="auth",algorithm=MD5-sess,nonce="+Upgraded+v1e4fcae181b935afc3d94f30f5033141a25e3c7e4b83bd101c60cf10ea425a352c8959c8d47e643e5fc38f90cffe411be5f7a99033900ae4d",charset=utf-8,realm="Digest"

Digest認證傳輸用戶憑證的哈希碼,而不是明文。客戶端首先匿名向服務器發送GET請求,服務器返回一個401響應,這個響應包含一個"WWW-Authenticate"報頭,攜帶的信息包括。

參數 解釋
Digest 認證方案
Realm="Digest" 領域
Algorithm 表示服務端支持的哈希算法,MD5-sess
Nonce 服務端生成的唯一性標示,一般來說,IIS會利用當前時間戳以及請求的Etag(被請求變量的實體值)報頭值來生成這個nonce
Qop(Quanlity of Protection) IIS采用qop通知客戶端采用的消息保護等級,可選值包括auth(authentication), auth-int(authentication-integrity),前者僅限於基本的認證,後者還確保傳輸內容的一致性。

輸入賬號密碼的再一次請求(響應為200成功):

Authorization: Digest username="cn1\\she_s", realm="Digest", nonce="+Upgraded+v1e4fcae181b935afc3d94f30f5033141a25e3c7e4b83bd101c60cf10ea425a352c8959c8d47e643e5fc38f90cffe411be5f7a99033900ae4d", uri="/Sory.Entertainment.WebAPI/", algorithm=MD5-sess, response="9a6cb99fad4404cdd521e5db432f6b09", qop="auth", nc=00000001, cnonce="c77c05d93544b363"

其相關參數為:

參數 解釋
Username 代表客戶端的用戶名,看來用戶名還是可以截取的
Qop 最終采用的消息保護等級, qop="auth"
Algorithm 最終采用的加密算法,MD5-sess
Nonce 實際就是服務器端生成的nonce
cnonce 客戶端生成的nonce(c代表client),它可以對請求內容簽名以確保內容未被篡改,可以幫助客戶端對服務端實施認證(服務端能夠證明知道該nonce,這些很適合防禦跨站請求偽造的防禦)
Nc(nonce count) 它表示客戶端針對同一個nonce發送請求的數量,一位著這是隨著請求不斷增加的數字,IIS可以通過nc代表的數字來防止"重放攻擊",它會維護每個nonce的nc,如果請求攜帶的nc比這個少,會被認為是不合法的請求。

IIS在接受到第二次請求後,它先對請求進行合法性校驗(比如nc的合法性),然後從Authentication報頭提取用戶名、nonce和加密算法計算出針對用戶名真正的Digest,最終利用它與請求中提供的Digest進行比較確認密碼的正確性,完成客戶端認證。

Tip:

<script type="application/json" id="__browserLink_initializationData">

{"appName":"Firefox","requestId":"ee1fc1d3f30e4b4cba937703bee3ce10"}

</script>

<script type="text/javascript" src="http://localhost:13820/69ea419b05a141aaa5111affa4bb02fe/browserLink" async="async"></script>

這部分如何理解,與jsonP相關?

  • 集成Windows認證, P610

無論問basic還是Digest認證,如果使用瀏覽器做客戶端,第一次訪問總需要在彈出框中輸入,非常繁瑣,並且密碼在網絡中傳輸,有安全風險,一般采用加鹽的方式避免。集成Windows認證可以很好解決該問題,它默認以登錄機器的Windows賬號的名義來訪問被授權的資源沒,用戶的密碼被包含在請求攜帶的安全令牌中,非常的方便,該方式最終使用NTLM和Kerberos協議來完成。

NTLM協議(比較陳舊):采用質詢/應答(Challenge/Response)消息交換模式,DC域控制器保存所用用戶的相關信息。基本流程為:步驟1,用戶輸入賬戶密碼登錄主機,主機會緩存輸入密碼的哈希值,原始密碼會丟失。如果視圖訪問服務器資源,需要向對方發送請求,請求中包含一個明文表示的用戶名;步驟2,服務端接受請求,生成16位隨機數(稱為質詢challenge),存儲起來後以明文的形式發送給客戶端;和Digest請求中nonce的意圖完全一致;步驟3,客戶端收到服務端的質詢後,用在步驟1中保存的密碼哈希值對其加密,然後將加密後的質詢發送給服務端;步驟4,服務端收到加密質詢後,會向DC發送針對客戶端的驗證請求(請求中包括,用戶名、客戶端密碼加密後的質詢和原始的質詢);步驟5、6,DC根據用戶名獲得密碼哈希值,對原始質詢加密,再與服務端發送的質詢比較,一致就為驗證通過,否則失敗。

Kerberos:這東西也算是困擾了小弟很多年,老看到,尤其每次註冊windows時,呵呵,你懂得。實際上它是一種更搞笑安全的認證協議,過程更加的復雜,與NTLM相似,也包含三部分,客戶端、服務器和KDC(Key Distribution Center,在windows域中,KDC有DC擔當)。Kerberos實際是一種基於票據(Ticket)的認證方式,客戶端要訪問服務端的資源,首先要購買服務端認可的票據。也就是說,客戶端在訪問服務器前要先買好票,等待服務器驗票後才能入場,但這票不能直接購買,首先需要認購權證(和糧票,股票認購權證相似)。這個認購權證和進入服務器的入場券均由KDC發售,感覺各種繞……相關詳細內容暫時放一放。

在IIS中使用windows集成驗證時,會看到provider的設置,有"negotiate"和"NTLM"兩個選項,默認使用前者,其Provider包括"Negotiate: Kerberos",當然也可以自定義。此外,客戶端需要在IE設置-》高級中,開啟Windows集成認證,默認是開啟的。在使用HttpClient時,可以使用以下方式,簡化調用。

技術分享 View Code

技術分享

可與獨立於windows系統的認證方式,以前做webform時,forms認證是用的最多的,當時還一直以為forms驗證也需要和windows相關,尤其是和webForm中的form相關,現在想想挺幼稚的,同時這個驗證可以和membership很好的搭配在一起。但實際上這種驗證方式是獨立的,適合自行維護用戶賬號和密碼的場景,也是絕大部分項目的場景。那麽接下來介紹forms認證是如何進行的,努力使自己真正的走出誤區。

Forms認證的流程設計4次的消息交換,其具體步驟如下所示。

步驟1:用戶通過瀏覽器匿名向IIS發起請求,假設地址為"/home",它會收到狀態為"302, Found"的相應,這是一個用於實現"重定向"的http響應,它通過location報頭表示的重定向地址指向登錄的頁面,之前訪問的地址將作為查詢字符串returnURL的值。

步驟2:瀏覽器接受到該請求後,針對重定向的地址發送請求,登錄頁面最終被呈現在瀏覽器。

步驟3:用戶輸入正確的用戶名密碼後提交表單,服務器在接受到請求之後提取它們對用戶實施認證,認證成功後,它會生成一個安全令牌或者認證票據。接下來,通過查詢字符串returnURL表示的原始請求地址,作為另一個狀態為"302, Found"響應的Location報頭,而經過加密/簽名的安全令牌作為該響應的Cookie

步驟4:這個代表安全令牌的Cookie將自動附加到瀏覽器後續的請求中,服務器直接利用它對請求實施認證。Cookie的名稱、過期策略以及采用的保護等級均可以通過配置來控制。在禁用Cookie的情況下,安全令牌會直接作為URL的一部分傳送。

Tip:

首先想補充補充的是原來的forms認證的配置通過如下配置,加上在login相關方法上加上[AllowAnonymous],然後IIS中設置啟用匿名認證和forms認證即可。

技術分享 View Code

在ASP.NET 5之後的版本配置方式有一些變化,為了和第三方認證OAuth集成,不需要配置文件的配置,而是通過如下代碼配置,如果添加往往會出錯。

技術分享 View Code

Cookie采用的保護等級,在IE設置中包括6個隱私等級,對cookie的管理程度各不相同,從cookie完全不可讀寫,到完全可讀寫,默認的等級為中,阻止沒有精簡隱私策略的第三方cookie。

昨天和同事聊天時,還註意到有的項目的logoff是直接跳轉頁面,而不是action,因此缺少清空session等服務器端信息的操作,在實際開發中也算是個易錯點。

技術分享

之前介紹的認證方式,都要求密碼(token)在網絡中進行傳輸,為了確保密碼不被竊取,需要用SSL\TLS對傳輸的內容實施保護。其中涉及很多安全相關的基礎知識點,這兒只做簡要介紹。

  1. 非對稱加密:保證消息機密性,涉及有一個公鑰和密鑰組成的密鑰對。
  2. 數字簽名:保證身份認證、防止抵賴Non-repudiation、消息一致性
  3. 數字證書:Digital Certificate, 也稱為公鑰證書Public Key Certificate,比如12306要求在客戶端安裝的服務器根證書,大部分基於X.509 V3證書標準,還可以稱為X.509證書。其實際上就是將某個密鑰對中的公鑰與某個主體Subject進行綁定的文件,其內容包括版本號V3,序列號,簽名算法(md5WithRSAEncryption)、頒發者(Issuer)、有效日期、主體信息、主題公鑰和公鑰算法,以及頒發者的數字簽名

Tip:對於數字證書想說的是,一定要把它才分開了理解,大體包含三部分,公鑰信息、簽名信息和其他信息。並且後面兩者都是為前者的安全送達服務的,簡而言之(如12306購買火車票場景,祝願大家都能買到過個幸福年,哈哈),網站通過要求用戶安裝根證書的方式將網站通信密鑰對中的公鑰發送給我,但為了保證這個過程的安全,就需要提供數字簽名的過程。就像將情報通訊密碼給我,並且簽上了FBI一樣,之後就可以用這個密碼進行通訊了。這個說的比較粗略,有些簡化,省略了認證權威機構和認證樹的概念。

關於SSL/TLS的概念,後者TLS(Transport Layer Security)其實是前者SSL(Secure Sockets Layer)的升級版本,TLS1.0就是SSL3.1,在IE的設置中,可以看到默認支持SSL 3.0和TLS1.0。而HTTPS是指HTTP與SSL/TLS的結合,像之前介紹的12306的安全,就是https的,也稱為弱安全模型,那麽強安全模型是什麽?那就是我們使用網銀時,大家都經歷安裝安全控件甚至使用U盾的過程,這兒就是強安全。簡單來說,強安全,指服務器端和客戶端都要安裝對方的證書,相互認證;弱安全,指客戶端安裝服務器證書,客戶端認證服務器。接下來介紹請求Https網站的過程。

步驟1:客戶端向https站點發送協商請求,包括客戶端所支持的加密算法列表

步驟2:Https站點從算法列表中選擇所能支持最合適安全級別的算法(安全性和效率折衷),連同綁定到該站點的數字證書一並發送給客戶端。

步驟3:客戶端接受證書後,通過驗證確認站點身份,成功後,生成一個隨機數,作為會話密鑰(Session key)緩存在客戶端。客戶端采用發回的加密算法,利用證書中的公鑰對該密鑰(Session Key)加密,加密後發送給站點,站點解密獲得Session key。

步驟4:客戶端和服務端使用該Session key使用對稱加密算法進行加解密。(對稱加密效率高,但密鑰管理難,因此采用結合兩者的方式,用非對稱加密管理密鑰,用密鑰來對稱加密,棒棒噠)

  • SSL/TLS在IIS中的應用

IIS對多種傳輸協議提供支持,包括http、Tcph和MSMQ等,站點綁定數字證書的方式喲很多,最方便的是用iis管理器,其步驟如下。

步驟1:在未目標站點添加https綁定之前,我們需要為它準備一張證書,可以用makeCert.exe工具,也可以使用iis管理器來創建自我簽名的證書。在IIS的特性列表中選擇"服務器證書",之後選擇"創建自我簽名證書",命名和站點名稱相同即可。

步驟2:在IIS中,選擇我們指定的站點(Web Site),右鍵選擇編輯綁定,在網站綁定頁面添加https類型並選擇相應的證書,在瀏覽網站欄就可以看到http, 和https了。這時你就可以瀏覽網頁通過兩種不同的方式,當然你自定義的證書未被加入根證書,因此用https時,瀏覽器會顯示一個小紅叉。之後在httpclient部分,你也會發現,我們可以通過設置,跳過客戶端對服務器證書的驗證,方便調用,不過不推薦。

網站的常見調用可以通過http和https兩種方式,但具體到某一個調用的時候,需要在"安全"和"性能"間權衡,但是認證過程必須采用https,將指定的action設置為[RequireHttps],那麽它就只能通過https協議訪問到。該特性實際是MVC提供的一個AuthenticationFilter,如果是一個普通請求,則會把該請求重定向到https的相應地址。這兒大家會註意到一個問題就是requiredHttps是MVC下的概念,那麽WebAPI中有對應概念麽?這個可以通過自定義的認證過濾器來處理。

技術分享 View Code

技術分享

一般來說,web應用的用戶認證均由自身完成,通過存儲用戶名和密碼並進行驗證,但這種方式在當前的互聯網場景下會有一下兩個主要問題:用戶需要註冊不同的賬號,記住和使用非常的麻煩了;對於應用提供者,大量認證系統會花費大量的精力。基於OAuth2.0(Open Authentication 2.0)的第三方認證模型的出現正好可以解決這個痛點,該模型借助了Google, 微信等值得信賴的IT服務提供商。OAuth是定義一種協議幫助資源的擁有者在不提供自身憑證的前提下授權第三方應用以他的名義存儲保護的資源。

獲得資源擁有者授權的第三方應用獲取受保護的資源采用的不是授權者憑證,而是一個被稱為Access Token的安全令牌,Access Token頒發過程會涉及若幹不同的角色。接下來通過一個蔣大師提到的簡單例子做相應的介紹。例如我們開發了一個集成了新浪微博認證用於發布打折商品信息的App,經過用戶授權之後它可以調用新浪微博的WebAPI獲取用戶的電子郵箱地址並發布相應的打折消息。那麽OAuth在該場景下的作用是,用戶授權該應用以自己名義調用新浪微博的webAPI獲取自己的郵箱地址,涉及4個角色:資源擁有者,一般為最終用戶;客戶端應用,需要獲得資源擁有者授權並最終訪問受保護資源的應用;資源服務器,最終承載資源的服務器,一本為一個webAPI;授權服務器,它對用戶和客戶端實施認證,並在用戶授權的情況下向客戶端應用頒發Access Token,在之前介紹的場景下,兩者合一,均為新浪微博。

一般來說,如果需要針對某個第三方認證服務來開發應用,需要向對應的認證服務提供商對應用進行註冊,成功後獲得AppID/AppSecet(名稱不一定一樣),實際工作中其實每個項目往往也有AppID。常見的,我們可以申請windows服務https://account.live.com/developers/applications/, 申請應用後可以獲取clientID和clientSecret,並且設置重定向的域名。這兒想提醒大家的一點,就是這個重定向設置可以是多個,並且一定要和你每一個請求的重定向設置對應起來,一旦沒有設置,windows live會報無法提供服務的錯誤。

技術分享

這兒流程類似於Kerberos認證,首先客戶端獲取授權憑證,之後再購買訪問憑證,最後訪問資源。Authorization grant(縮寫AG)包含4中類型:Implicit,省略了獲取AG過程;Authorization Code, 標準模式,這個AG是一個授權碼;之後的兩種不太有價值,就不介紹了。

  • Implicit Authorization Grant簡寫IMP,例子如下(需要修改host), P640,比較麻煩的部分。

該模型中,通過獲取當前請求的AccessToken,之後調用Windows Live Connect提供的API(https://apis.live.net/v5.0/me)。不過在此之前,如果用戶未登陸到Windows Live,那麽首先會跳轉到登陸頁面,完成GetProfile調用後將json格式字符串顯示在瀏覽器中。這兒的核心是,我們通過AuthenticateAttribute將AccessToken寫入Cookie中,這與Forms認證相似,不過從安全角度講,利用Cookie攜帶安全令牌會引起被稱為"跨站請求偽造CSRF, Cross-Site Request Forgery"的安全問題,所以用htto報頭來作為安全令牌的載體比較合理。在IAuthenticationFilter接口的ChallengeAsync用於在認證過程中向客戶端發送"質詢"響應,如果AccessToken不存在,就像WindowLive授權頁面重定向,參數(response-type, redirect_uri, client, scope)以查詢字符串形式提供。而IActionFilter中的方法ExecuteActionFilterAsync用於將AccessToken寫入cookie。代碼如下所示:

技術分享 View Code

Tip:

location是javascript裏邊管理地址欄的內置對象,比如location.href就管理頁面的url,用location.href=url就可以直接將頁面重定向url。而location.hash則可以用來獲取或設置頁面的標簽值。比如http://domain/#admin的location.hash="#admin"。利用這個屬性值可以做一個非常有意義的事情。簡單來說就是"#"號後面跟著的內容,類似於查詢字符串。

window.location.hash這個屬性可讀可寫。讀取時,可以用來判斷網頁狀態是否改變;寫入時,則會在不重載網頁的前提下,創造一條訪問歷史記錄。

  • Authorization Code Authorization Grant(簡寫AC)

之前介紹的IMP存在兩個問題,其一,授權服務器沒有對客戶端應用進行認證,因為獲取Access Token的請求只提供了客戶端應用的ClientID而沒有ClientSecret;其二,Access Token是授權服務器單獨頒發給客戶端應用的,應該對於其他人是不可見(包括擁有被訪問資源的授權者)。IMP類型授權的客戶端運行於純客戶端上下文環境,AC類型的使用戶運行於服務器的應用,比如MVC應用中的Controller。

步驟1:客戶端向授權服務器發送一個獲取Authentication Code(認購權證)的請求,請求的地址和參數和IMP相似。

參數名 解釋
Response_type 表示請求希望獲取的對象類型,在此我們希望獲取的是Authorization Code
Redirect_uri 表示授權服務器在獲得用戶授權並完成對用戶認證後重定向的地址,AC就是以查詢字符串方式附加
Client_id 授權客戶端應用的clint_id
Scope 表示授權的範圍,根據具體需要的權限集而定

步驟2:客戶端利用AC向授權服務器獲取Access Token,一般為POST請求,參數包括:

參數名 解釋
Client 授權客戶端應用的clint_id
Client_secret 該標識對應的ClientSecret
Redirect_uri 之前獲取AC時指定的重定向地址
Grant_type 采用Authorization Grant類型,值為"authorization_code"

授權服務器接受到請求後,除了利用clientID和Secret對客戶端實施驗證外,還會檢查重定向地址是否一致,完成後,生成一個AccessToken發還。消息包括:token_type,bearer;expires_in,3600;scope,wl.signin wl.basic;access_token;authentication_token。

出於安全考慮,access token有一個過期時限,此外授權服務器還會返回一個長期有效的安全令牌,當ac token過期時,可以利用它再獲取,使用它需要在scope中加入"wl.offline_access",相關代碼如下所示。

對了,實際使用中,不需要這麽麻煩,你可以看到在project的app_start的StartupAuth中,可以看到微軟的設置,只用輸入對應的clientId和clientSecret。

Tip:

一個問題,為什麽我設置的www.sory.com可以訪問到,而我並未申請該域名和綁定IP?

技術分享

WebAPI采用REST風格,將瀏覽器作為執行上下文客戶端js應用是主要消費者,但"同源策略"限制了js的跨站點調用,這將導致WebAPI不能跨域訪問資源,那麽它將"名不副實",如何解決這個問題呢?將在後面意義道來,主要有jsonP和cros規範兩種方式。

瀏覽器作為internet工具,它為客戶端應用提供一個寄宿和運行的環境。這個應用就是javaScript程序,由於js腳本並非都值得信奈,所以對js運行限制在一個沙盒sandbox中。同源策略是一項最基本的安全策略,是瀏覽器安全的基礎,它限制了來自A站點的腳本只能操作A的頁面的DOM,跨域操作B站點的資源將會被拒絕。同源要求一下3方面相同:主機名稱(域名/子域名或者IP地址);端口號;網絡協議(Schema)。需要註意的,對於一段js腳本來說,其"源"與它存儲的地址無關,而取決於腳本被加載的頁面,JSONP就利用了這個特性。除了<script>標簽,html還有其他一些具有src屬性的標簽(<img><iframe><link>)均具有跨域加載資源的能力,對於這些標簽,每次加載都涉及一個GET請求。同源策略主要針對Ajax請求,該策略主要限制了通過XMLHttpRequest發送的Ajax請求,如果是一個異源地址,瀏覽器將拒絕讀取返回的內容。

一個跨域訪問的小例子,一個MVC的應用去調用一個webAPI應用的服務,兩者在不同的接口下時。

技術分享 View Code

跨域調用的錯誤信息:XMLHttpRequest cannot load http://www.sory.com/Sory.Entertainment.WebAPI/api/contact. No ‘Access-Control-Allow-Origin‘ header is present on the requested resource. Origin ‘http://localhost:26829‘ is therefore not allowed access.

  • JSONP方式

之前說過,js腳本的源有加載頁面決定,而不是存儲地址。對於一段<script>標簽src屬性加在的js腳本,它與當前頁面同源。對於之前的例子來說,可以將聯系人列表的呈現單獨定義在listContacts函數中,並將WebAPI的地址置於<script>標簽的src屬性中來間接調用。

技術分享

命名空間:System.Net.Http,簡化了我們原有的HttpWebRequest的調用模式。

基本使用:

HttpResponseMessage response = client.GetAsync("http://...").Result;

Cw(response.Content.ReadAsAsync<DateTime>().Result.ToString();(這兒的result與await很類似啊, Task<long>)

  • 利用httpClient調用Basic認證下的WebAPI

這兒需要註意,首先在nuget中獲取httpClient相關組件,其依賴於Microsoft.Bcl庫,部分擴展方法需要添加相應命名空間,自己找了半天ReadAsync<T>這個泛型方法半天沒找到,也可以自己寫一個,比較簡單方便。

技術分享 View Code
  • 利用httpClient調用forms認證下的WebAPI

在Froms認證時,我們首先需要請求login頁面,將用戶名密碼作為token發送給服務器,之後獲取服務器響應信息head中的"Set-Cookie"屬性,接著獲取其中key為".ASPXAUTH"的cookie信息,這個也就是服務器端和客戶端通信的token。之後再在自己真正需要的請求中,附加上該token(用FormUrlEncodeContent打包,這個類實際氣的就是原來mediaType="application/x-www-form-urlencoded"的作用),還有要註意的是httpClientHandler中需要初始化CookieContainer。

技術分享 View Code

參考資料:

  1. 蔣金楠. ASP.NET Web API 2框架揭秘[M]. 北京:電子工業出版社, 2014.
  2. (美)加洛韋. ASP.NET MVC 5高級編程(第5版)[M]. 北京:清華大學出版社, 2015.

快速入門系列--WebAPI--01基礎