JS跨域解決方案之使用CORS實(shí)現(xiàn)跨域
引言
跨域是我在日常面試中經(jīng)常會問到的問題,這詞在前端界出現(xiàn)的頻率不低,主要原因還是由于安全限制(同源策略, 即JavaScript或Cookie只能訪問同域下的內(nèi)容),因?yàn)槲覀冊谌粘5捻?xiàng)目開發(fā)時會不可避免的需要進(jìn)行跨域操作,所以跨域能力也算是前端工程師的基本功之一。
和大多數(shù)跨域的解決方案一樣,JSONP也是我的選擇,可是某天PM的需求變了,某功能需要改成支持POST,因?yàn)閭鬏數(shù)臄?shù)據(jù)量比較大,GET形式搞不定。所以折騰了下聞名已久的CORS(跨域資源共享,Cross-Origin Resource Sharing),這邊文章也就是折騰期間的小記與總結(jié)。
•CORS能做什么:
正常使用AJAX會需要正??紤]跨域問題,所以偉大的程序員們又折騰出了一系列跨域問題的解決方案,如JSONP、flash、ifame、xhr2等等。
• CORS的原理:
CORS定義一種跨域訪問的機(jī)制,可以讓AJAX實(shí)現(xiàn)跨域訪問。CORS 允許一個域上的網(wǎng)絡(luò)應(yīng)用向另一個域提交跨域 AJAX 請求。實(shí)現(xiàn)此功能非常簡單,只需由服務(wù)器發(fā)送一個響應(yīng)標(biāo)頭即可。
下面我們步入正題具體詳情如下所示:
跨站HTTP請求(Cross-site HTTP request)是指發(fā)起請求的資源所在域不同于請求指向的資源所在域的HTTP請求。
比如說,我在Web網(wǎng)站A(www.a.com)中通過<img>標(biāo)簽引入了B站的資源(www.b.com/images/1.jpg),那么A站會向B站發(fā)起一個跨站請求。
這種圖片資源的跨站請求是被允許的,類似的跨站請求還有CSS文件,JavaScript文件等。
但是如果是在腳本中發(fā)起HTTP請求,出于安全考慮,會被瀏覽器限制。比如,使用 XMLHttpRequest 對象發(fā)起 HTTP 請求就必須遵守 同源策略。
所謂“同源策略”是指Web應(yīng)用程序只能使用 XMLHttpRequest 對象向發(fā)起源所在域內(nèi)發(fā)起HTTP請求,這個請求源和請求對象必須在一個域內(nèi)。
舉例來說,http://www.a.com,這個網(wǎng)址的協(xié)議是http,域名是www.a.com,端口默認(rèn)是80。那么以下是它的同源情況:
•http://www.a.com/index.html 同源
•https://www.a.com/a.html 不同源(協(xié)議不同)
•http://service.a.com/testService/test 不同源(域名不同)
•http://www.b.com/index.html 不同源(域名不同)
•http://www.a.com:8080/index.html 不同源(端口不同)
為了開發(fā)出更強(qiáng)大,更豐富的Web應(yīng)用,跨域請求是很常見的,那么如何在不舍棄安全的情況下進(jìn)行跨域請求呢?
W3C推薦了一種新的機(jī)制,即跨源資源共享(Cross-Origin Resource Sharing (CORS))。
跨源資源共享(CORS)是通過客戶端+服務(wù)端協(xié)作聲明的方式來確保請求安全的。服務(wù)端會在HTTP請求頭中增加一系列HTTP請求參數(shù)(例如Access-Control-Allow-Origin等),來限制哪些域的請求和哪些請求類型可以接受,而客戶端在發(fā)起請求時必須聲明自己的源(Orgin),否則服務(wù)器將不予處理,如果客戶端不作聲明,請求甚至?xí)粸g覽器直接攔截都到不了服務(wù)端。服務(wù)端收到HTTP請求后會進(jìn)行域的比較,只有同域的請求才會處理。
一個使用CORS實(shí)現(xiàn)跨域請求的示例:
客戶端:
function getHello() { var xhr = new XMLHttpRequest(); xhr.open("post", "http://b.example.com/Test.ashx", true); xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); // 聲明請求源 xhr.setRequestHeader("Origin", "http://a.example.com"); xhr.onreadystatechange = function () { if (xhr.readyState == 4 && xhr.status == 200) { var responseText = xhr.responseText; console.info(responseText); } } xhr.send(); }
服務(wù)端:
public class Test : IHttpHandler { public void ProcessRequest(HttpContext context) { context.Response.ContentType = "text/plain"; // 聲明接受所有域的請求 context.Response.AddHeader("Access-Control-Allow-Origin", "*"); context.Response.Write("Hello World"); } public bool IsReusable { get { return false; } } }
在Web API中啟用跨域訪問
CORS是服務(wù)端和客戶端協(xié)作聲明來確保請求安全的,因此,如果需要在Web API中啟用CORS也需要進(jìn)行相應(yīng)配置。好在微軟的ASP.NET團(tuán)隊(duì)提供了官方的支持跨域的解決方案,只需要在NuGet中添加即可。
然后在App_Start/WebApiConfig.cs進(jìn)行如下配置即可實(shí)現(xiàn)跨域訪問:
public static class WebApiConfig { public static void Register(HttpConfiguration config) { // Web API 配置和服務(wù) // 將 Web API 配置為僅使用不記名令牌身份驗(yàn)證。 config.SuppressDefaultHostAuthentication(); config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType)); // Web API 路由 config.MapHttpAttributeRoutes(); config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional } ); // 允許Web API跨域訪問 EnableCrossSiteRequests(config); config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html")); } private static void EnableCrossSiteRequests(HttpConfiguration config) { var cors = new EnableCorsAttribute( origins: "*", headers: "*", methods: "*" ); config.EnableCors(cors); } }
由于IE10以下瀏覽器不支持CORS,所以目前在國內(nèi)CORS并不是主流的跨域解決方案,但是隨著windows 10的發(fā)布,IE的逐漸衰落,可以預(yù)見,在不遠(yuǎn)的將來CORS將成為跨域的標(biāo)準(zhǔn)解決方案。
以上所述是小編給大家介紹的JS跨域解決方案之使用CORS實(shí)現(xiàn)跨域,希望對大家有所幫助!
相關(guān)文章
js實(shí)現(xiàn)隨機(jī)點(diǎn)名系統(tǒng)(實(shí)例講解)
下面小編就為大家?guī)硪黄猨s實(shí)現(xiàn)隨機(jī)點(diǎn)名系統(tǒng)(實(shí)例講解)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-10-10JavaScript中的console.group()函數(shù)詳細(xì)介紹
這篇文章主要介紹了JavaScript中的console.group()函數(shù)詳細(xì)介紹,當(dāng)程序調(diào)試日志過多時會有些雜亂,此時可以使用console.group()函數(shù)調(diào)來分組顯示,需要的朋友可以參考下2014-12-12整理Javascript流程控制語句學(xué)習(xí)筆記
整理Javascript流程控制語句學(xué)習(xí)筆記,之前一系列的文章是跟我學(xué)習(xí)Javascript,本文就是進(jìn)一步學(xué)習(xí)javascript流程控制語句,希望大家繼續(xù)關(guān)注2015-11-11微信小程序?qū)崿F(xiàn)之手勢鎖功能實(shí)例代碼
這篇文章主要介紹了微信小程序?qū)崿F(xiàn)之手勢鎖功能的實(shí)例代碼,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下2018-07-07JavaScript將數(shù)組轉(zhuǎn)換成CSV格式的方法
這篇文章主要介紹了JavaScript將數(shù)組轉(zhuǎn)換成CSV格式的方法,實(shí)例分析了javascript使用valueOf方法將數(shù)組值轉(zhuǎn)換為csv格式字符串的技巧,非常具有實(shí)用價值,需要的朋友可以參考下2015-03-03