如何实现跨域?
跨域是個比較古老的命題了,歷史上跨域的實現手段有很多,我們現在主要介紹三種比較主流的跨域方案,其余的方案我們就不深入討論了,因為使用場景很少,也沒必要記這么多奇技淫巧。
1. 最經典的跨域方案jsonp
jsonp本質上是一個Hack,它利用<script>標簽不受同源策略限制的特性進行跨域操作。
jsonp優點:
實現簡單
兼容性非常好
jsonp的缺點:
只支持get請求(因為<script>標簽只能get)
有安全性問題,容易遭受xss攻擊
需要服務端配合jsonp進行一定程度的改造
Jsonp的原理:
function JSONP({ url,params,callbackKey,callback }) {// 在參數里制定 callback 的名字params = params || {}params[callbackKey] = 'jsonpCallback'// 預留 callbackwindow.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)} })2. 最流行的跨域方案cors
cors是目前主流的跨域解決方案,跨域資源共享(CORS) 是一種機制,它使用額外的 HTTP 頭來告訴瀏覽器 讓運行在一個 origin (domain) 上的Web應用被準許訪問來自不同源服務器上的指定的資源。當一個資源從與該資源本身所在的服務器不同的域、協議或端口請求一個資源時,資源會發起一個跨域 HTTP 請求。
如果你用express,可以這樣在后端設置
?
3. 最方便的跨域方案Nginx
在生產環境中建議用成熟的開源中間件解決問題。
nginx是一款極其強大的web服務器,其優點就是輕量級、啟動快、高并發。
現在的新項目中nginx幾乎是首選,我們用node或者java開發的服務通常都需要經過nginx的反向代理。
反向代理的原理很簡單,即所有客戶端的請求都必須先經過nginx的處理,nginx作為代理服務器再講請求轉發給node或者java服務,這樣就規避了同源策略。
#進程, 可更具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.htmllocation / {root html;index index.html index.htm;}# localhost/api 的請求會被轉發到192.168.0.103:8080location /api {rewrite ^/b/(.*)$ /$1 break; # 去除本地接口/api前綴, 否則會出現404proxy_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.htmlerror_page 500 502 503 504 /50x.html;location = /50x.html {root html;}}}其它跨域方案
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為基礎主域,就實現了同域
總結
- 上一篇: 未知的软件异常0xc0000409解决办
- 下一篇: html网页如何限制ip访问量,Ngin