提及來源...今天去茶水間倒水時,偶然聽到公司面試官在問面試者前端跨域的如何解決。我心中默默想了一想,啪啪啪瞬間想出幾個關鍵詞,iframe,cors,同源策略,jsonp...轉念一想,雖然這是很常見的面試題,然而我在開發過程當中,還真沒有用過jsonp這種方式...就連原理也說很差。一陣冷汗,? ,趕忙去找了相關資料。javascript
對於同源策略,在這裏我就很少累贅敘述了,簡單來講,若是如下三項:同一協議、同一域名、同一端口但凡是有一項不知足,瀏覽器就會把 No 'Access-Control-Allow-Origin' header is present on the requested resource
甩你一臉。前端
跨域問題能夠說在前端方面不可避免,但同源策略畢竟在保護網絡信息安全方面起到很大的做用。試想若是沒有同源策略,別的網頁能夠輕鬆竊取你的cookie,而假如你的cookie中存有你的我的信息...太可怕了,不過話說回來同源策略帶來的跨域問題也很頭疼,幸虧如今已經有多種方式可以解決。java
CORS 跨域資源共享策略(web
JSONP面試
window.nameajax
document.domain(主域相同的狀況下可用)json
postMessage(h5新引入)跨域
websocket(h5新引入,不受同源策略限制,因此說h5真是個好東西...?)瀏覽器
...安全
因爲篇幅有限(好吧...實際上是我寫不了那麼多),在這裏對於其餘解決方式就不一一詳解了。
JSONP
是 JSON with Padding
的簡稱,是一種較爲經常使用的解決跨域訪問的方式。咱們先來看一段示例代碼:
ajax({//此ajax方法是封裝了XMLHttpRequest對象實現,具體代碼與本文無關就不貼了 method : 'get', url : 'http://127.0.0.1:8787', data : { 'name' : '小明',//此ajax方法會自動將數據以get方式提交 'age' : 22 }, success : function (message) { alert(message); }, async : true })
上面的代碼很簡單,瀏覽器端發起了一個異步ajax請求,讓咱們來看看服務端代碼:
app.get('*', function(req, res) {//這裏只截取了關鍵代碼 res.send("測試數據"); });
清晰,易懂~so,what happend?
不出所料,瀏覽器甩了我一臉...
易地再戰!JSONP炸裂出場~
function showJsonp(obj){ console.log(obj.message); } var url = 'http://127.0.0.1:8787/?func=showJsonp' var script = document.createElement('script'); script.setAttribute('src',url); script.setAttribute('type','text/javascript'); document.getElementsByTagName('head')[0].appendChild(script);
再來後臺代碼~
app.get('*', function(req, res) { let callback = req.query.func; let content = callback+"({'message':'測試數據2'})"; res.send(content); });
結果:
大!獲!全!勝!
是時候分析一波戰術策略了~在日常寫代碼的時候,可能不少人沒有注意,瀏覽器對於script,iframe等標籤的src等屬性,是沒有同源策略限制的。而jsonp就很好的利用了這一點~在咱們發起請求時,url後跟了一個名爲func
的參數,而這個參數就是以後須要用到的回調函數名稱。
咱們經過動態插入script
標籤的方式,利用script標籤的src屬性發起請求,瀏覽器不會以同源策略來找事...然後臺根據請求構造出的數據長啥樣呢?
showJsonp({'message':'測試數據2'})
告訴我!這段代碼插入你的script標籤內後,會發生啥?!
固然是執行早就定義好的showJsonp函數啊~
bingo,完美解決跨域問題~~
jsonp的方式兼容性很是好,即使是那些老古董瀏覽器,也能夠用jsonp的方式解決跨域問題,可是它也有所限制,它只能使用get方式發起請求,而且對於不一樣域之間頁面的js互相調用無能爲力。