跨域與前后端分離


百度關於跨域的文章幾乎每個文章都會有這么一個圖和這幾個解決方案

image.png

只要是跟當前頁面所在url不同的請求都屬於跨域請求,為什么我可以訪問cdn或者引入其他網站的js或者css或者圖片,那是因為src這個標簽是支持跨域的,你用ajax去獲取外網的js,css,圖片試試,所以把頁面放在跟請求一個地址的服務器里面,就是最強的解決跨域的方案

從jq-ajax文章過來的可以回去了,下面的內容超綱了

vue-cli是啟動了一個開發版的本地服務器,域名是localhost:端口,在腳手架里寫請求自然不可能,那就只能寫完打包出來,把打包文件放到跟請求同一個域名的服務器里咯,這個雖然可以,但是也太傻了,改一下打包一下發布一下,還是看看其他解決跨域的方案吧

解決跨域方案

  1. 通過jsonp跨域(只能跨域get請求)
  2. document.domain + iframe跨域
  3. location.hash + iframe
  4. window.name + iframe跨域
  5. postMessage跨域
  6. 跨域資源共享(CORS)
  7. nginx代理跨域
  8. nodejs中間件代理跨域
  9. WebSocket協議跨域

上面的方案我們只取第六點,第7點,第八點,【7和8是一樣的】

再看回axios篇里的這句代碼

baseURL: process.env.NODE_ENV === 'development' ? '/proxy' : 'http://xxx.com',

需要解決的問題有

  • 線上正式版跨域調不通
  • 本地開發跨域調不通

線上正式版跨域調不通
首先就是要服務端支持跨域,叫做CORS,這個你要讓后端去設置,如果是java和nodejs的開發,查看筆記有代碼可以復制,開啟CORShttp://xxx.com就支持跨域了,也就是打包完成后你放在http://aaa.com請求http://xxx.com的所有請求都可以了

本地開發跨域調不通
既然線上都開啟CORS了,本地也可以開啟CORS,然后把上面的代碼改成

baseURL: process.env.NODE_ENV === 'development' ? 'http://localhost:后端的本地端口' : 'http://xxx.com',

行不行,個人測試不行,其實應該是可以的,但不知道什么原因,所以還是用上面的方法吧
既然瀏覽器不能跨域,就讓本地服務器去請求后轉給你,也就是讓localhost:端口這個服務器去請求,上面的這個/proxy是簡寫,實際是localhost:端口/proxy,可以理解吧,為什么要加上這個值呢,這個值就是一個標識而且,改成aa,bb也行,這個值就是為了告訴腳手架服務器,你如果看到有請求帶有這個標識,你就替我去另一個地址把請求數據拿過來

問題是我怎么讓服務器有這個功能,vue-cli自帶的有個proxy插件,配置一下就行
在vue.config.js里

devServer: {
    port: port,
    open: true,
    overlay: {
      warnings: false,
      errors: true
    },
    proxy: {
      // 這個就是被監聽的標識
      "/proxy": {
        // 然后腳手架去這個地址請求數據,這個就是本地的后端服務器以及端口
        target: "http://127.0.0.1:8080/",
        changeOrigin: true,
        pathRewrite: { '^/proxy': '' },
     }
   }
}

proxy的配置后很多,這個是最基礎的寫法,如果有其他需求,可以查一下百度

這時本地的腳手架應該就能調通本地的接口了,線上的項目也能調通線上的接口了,問題都解決了,就是一句baseURL的三元運算符和幾行proxy的配置而已,本來不應該寫這么多的,上代碼自行理解就行,但是還是想解釋一下,一解釋就寫了兩篇筆記出來

談談前后端分離
這是一道面試題來的

前后端不分離
特點是:頁面完全后后端模板生成,數據由后端渲染
比如node的ejs模板渲染
比如java的jstl和jsp渲染
這些寫法需要專門去學,不是正常的html標簽,如今已經都淘汰了,因為很少有人懂了,維護成本特別高

前后端半分離
就是把項目跟服務器放在同個服務器里,很常見的很普通的開發模式,jq時代

前后端分離
就是前端代碼一個服務器,后端代碼一個服務器,開啟跨域支持,自己開發完更新自己的代碼就行,但是前后端分離就失去了同源策略,如果缺少了同源策略,瀏覽器很容易受到 XSS、CSFR 等攻擊,可以查看無分類的《安全和攻擊》筆記

補充jsonp
面試題來着,但正常不會用,以前豆瓣和百度的搜索接口就是用jsonp實現的
jsonp是怎么實現的,原理就是你把一個全局的方法名作為參數傳給后端,比如參數叫cb,后端接口到參數后,查數據庫然后把數據包在參數里,返回值如下,並且把返回值設置成js格式,數據返回后就會自動的執行全局的cb方法,這個方法的參數就是跨域的數據

cb('{"name":"name"}')

jq使用jsonp

$.ajax({
    type : "get",
    url : "http://xxxx",
    dataType: "jsonp",
    jsonp:"callback",
    jsonpCallback: "doo",
    success : function(data) {
        console.log(data);
    }
});

fetch和axios沒有jsonp,需要自己封裝

(function (window,document) {
    "use strict";
    var jsonp = function (url,data,callback) {

        // 1.將傳入的data數據轉化為url字符串形式
        // {id:1,name:'jack'} => id=1&name=jack
        var dataString = url.indexof('?') == -1? '?': '&';
        for(var key in data){
            dataString += key + '=' + data[key] + '&';
        };

        // 2 處理url中的回調函數
        // cbFuncName回調函數的名字 :my_json_cb_名字的前綴 + 隨機數(把小數點去掉)
        var cbFuncName = 'my_json_cb_' + Math.random().toString().replace('.','');
        dataString += 'callback=' + cbFuncName;

        // 3.創建一個script標簽並插入到頁面中
        var scriptEle = document.createElement('script');
        scriptEle.src = url + dataString;

        // 4.掛載回調函數
        window[cbFuncName] = function (data) {
            callback(data);
            // 處理完回調函數的數據之后,刪除jsonp的script標簽
            document.body.removeChild(scriptEle);
        }

        document.body.appendChild(scriptEle);
    }

    window.$jsonp = jsonp;

})(window,document)

補充WebSocket
WebSocket 是一種雙向通信協議,也就是qq,微信的聊天原理,在建立連接之后,WebSocket的 server與 client都能主動向對方發送或接收數據而不受同源策略的限制。

function WebSocketTest(){
    if ("WebSocket" in window){
        alert("您的瀏覽器支持 WebSocket!");
        // 打開一個 web socket
        var ws = new WebSocket("ws://localhost:3000/abcd");
        ws.onopen = function(){
            // Web Socket 已連接上,使用 send() 方法發送數據
            ws.send("發送數據");
            alert("數據發送中...");
        };
        ws.onmessage = function (evt) {
            var received_msg = evt.data;
            alert("數據已接收...");
        };
        ws.onclose = function(){
            // 關閉 websocket
            alert("連接已關閉...");
        };
    } else{
        // 瀏覽器不支持 WebSocket
        alert("您的瀏覽器不支持 WebSocket!");
    }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM