如何實現跨域?


1.最經典的跨域方案jsonp
jsonp本質上是一個Hack,它利用<script>標簽不受同源策略限制的特性進行跨域操作。
jsonp優點:
實現簡單
兼容性非常好

jsonp的缺點:
只支持get請求(因為<script>標簽只能get)
有安全性問題,容易遭受xss攻擊
需要服務端配合jsonp進行一定程度的改造

        <script type="text/javascript">
            function JSONP({  
              url,
              params,
              callbackKey,
              callback
            }) {
              // 在參數里制定 callback 的名字
              params = params || {}
              params[callbackKey] = 'jsonpCallback'
                // 預留 callback
              window.jsonpCallback = callback
                // 拼接參數字符串
              const paramKeys = Object.keys(params)
              const paramString = paramKeys
                .map(key => `${key}=${params[key]}`)
                .join('&')
                // 插入 DOM 元素
              const script = document.createElement('script')
              script.setAttribute('src', `${url}?${paramString}`)
              document.body.appendChild(script)
            }
            
            JSONP({  
              url: 'http://s.weibo.com/ajax/jsonp/suggestion',
              params: {
                key: 'test',
              },
              callbackKey: '_cb',
              callback(result) {
                console.log(result.data)
              }
            })
        </script>

2.最流行的跨域方案cors
cors是目前主流的跨域解決方案,跨域資源共享(CORS) 是一種機制,它使用額外的 HTTP 頭來告訴瀏覽器
讓運行在一個 origin (domain) 上的Web應用被准許訪問來自不同源服務器上的指定的資源。
當一個資源從與該資源本身所在的服務器不同的域、協議或端口請求一個資源時,資源會發起一個跨域 HTTP 請求。
如果你用express,可以這樣在后端設置

        <script type="text/javascript">
            //CORS middleware
            var allowCrossDomain = function(req, res, next) {
                res.header('Access-Control-Allow-Origin', 'http://example.com');
                res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
                res.header('Access-Control-Allow-Headers', 'Content-Type');
            
                next();
            }
            
            //...
            app.configure(function() {
                app.use(express.bodyParser());
                app.use(express.cookieParser());
                app.use(express.session({ secret: 'cool beans' }));
                app.use(express.methodOverride());
                app.use(allowCrossDomain);
                app.use(app.router);
                app.use(express.static(__dirname + '/public'));
            });
        </script>

3.最方便的跨域方案Nginx
nginx是一款極其強大的web服務器,其優點就是輕量級、啟動快、高並發。
現在的新項目中nginx幾乎是首選,我們用node或者java開發的服務通常都需要經過nginx的反向代理。
反向代理的原理很簡單,即所有客戶端的請求都必須先經過nginx的處理,nginx作為代理服務器再講請求轉發給node或者java服務,這樣就規避了同源策略。

        <script type="text/javascript">
            #進程, 可更具cpu數量調整
            worker_processes  1;
            
            events {
                #連接數
                worker_connections  1024;
            }
            
            http {
                include       mime.types;
                default_type  application/octet-stream;
            
                sendfile        on;
            
                #連接超時時間,服務器會在這個時間過后關閉連接。
                keepalive_timeout  10;
            
                # gizp壓縮
                gzip  on;
            
                # 直接請求nginx也是會報跨域錯誤的這里設置允許跨域
                # 如果代理地址已經允許跨域則不需要這些, 否則報錯(雖然這樣nginx跨域就沒意義了)
                add_header Access-Control-Allow-Origin *;
                add_header Access-Control-Allow-Headers X-Requested-With;
                add_header Access-Control-Allow-Methods GET,POST,OPTIONS;
            
                # srever模塊配置是http模塊中的一個子模塊,用來定義一個虛擬訪問主機
                server {
                    listen       80;
                    server_name  localhost;
                    
                    # 根路徑指到index.html
                    location / {
                        root   html;
                        index  index.html index.htm;
                    }
            
                    # localhost/api 的請求會被轉發到192.168.0.103:8080
                    location /api {
                        rewrite ^/b/(.*)$ /$1 break; # 去除本地接口/api前綴, 否則會出現404
                        proxy_set_header Host $host;
                        proxy_set_header X-Real-IP $remote_addr;
                        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                        proxy_pass http://192.168.0.103:8080; # 轉發地址
                    }
                    
                    # 重定向錯誤頁面到/50x.html
                    error_page   500 502 503 504  /50x.html;
                    location = /50x.html {
                        root   html;
                    }
            
                }
            
            }
        </script>

4.其它跨域方案
HTML5 XMLHttpRequest 有一個API,postMessage()方法允許來自不同源的腳本采用異步方式進行有限的通信,可以實現跨文本檔、多窗口、跨域消息傳遞。
WebSocket 是一種雙向通信協議,在建立連接之后,WebSocket 的 server 與 client 都能主動向對方發送或接收數據,連接建立好了之后 client 與 server 之間的雙向通信就與 HTTP 無關了,因此可以跨域。
window.name + iframe:window.name屬性值在不同的頁面(甚至不同域名)加載后依舊存在,並且可以支持非常長的 name 值,我們可以利用這個特點進行跨域。
location.hash + iframe:a.html欲與c.html跨域相互通信,通過中間頁b.html來實現。 三個頁面,不同域之間利用iframe的location.hash傳值,相同域之間直接js訪問來通信。
document.domain + iframe: 該方式只能用於二級域名相同的情況下,比如 a.test.com 和 b.test.com 適用於該方式,我們只需要給頁面添加 document.domain ='test.com' 表示二級域名都相同就可以實現跨域,兩個頁面都通過js強制設置document.domain為基礎主域,就實現了同域。

6.其余方案來源於九種跨域方式


免責聲明!

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



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