前端跨域問題總結

首先,瀏覽器爲什麼要採用同源策略對跨域請求進行限制?

CSRF(Cross-site request forgery),中文名稱:跨站請求僞造。限制跨域是指限制兩個網站相互讀寫對方的數據,合理性顯而易見。能夠這麼理解CSRF攻擊:攻擊者盜用了你的身份,以你的名義發送惡意請求。CSRF可以作的事情包括:以你名義發送郵件,發消息,盜取你的帳號,甚至於購買商品,虛擬貨幣轉帳......形成的問題包括:我的隱私泄露以及財產安全。
javascript


更多歷史背景和實際案例可參照知乎連接:

https://www.zhihu.com/question/26379635
html


其次,經常使用解決方案:

前端項目集成nodejs - request模塊

本地localhost啓動一nodejs服務,添加一路由,代碼舉例以下:前端

router.get('/sina', function(req, res, next) { 
    console.log('req.headers: ', req.headers);  
    request('http://sina.com', function(error, response, data) {    
        console.log('error: ', error);    
        console.log('response: ', response.statusCode);    
        console.log('typeof(data): ', typeof(data));    
        console.log('data: ', data.length);    
        res.send({body: 'body'})
    })
})複製代碼

此場景下,http://sina.com是能夠被成功訪問的。我的理解就是此處是從一本地服務器訪問sina.com,至關於規避掉了瀏覽器的跨域訪問限制。且前端項目集成了nodejs後,可在nodejs中去管理維護後端接口的調用,同時可在Linux服務器上採用PM2工具,單獨部署項目。java


被調用方 - NGINX解決方案

虛擬主機:多個域名指向同一個服務器,服務器根據不一樣域名,將請求轉向不一樣應用服務器,看上去好像有多個主機,實際上只有一個主機。node


先進行被調用方虛擬主機的配置:nginx

先進行host的配置:web

打開windows下的hosts文件,編輯,先映射一個本地域名:ajax

127.0.0.1 b.com複製代碼

用b.com表示被調用方的域名。apache

而後打開nginx下的conf目錄,新建vhost文件夾,用於存放虛擬主機的配置文件,實際工做中通常就採用這種習慣;打開nginx.conf文件,在最後一行添加代碼windows

include vhost/*.conf;複製代碼

要nginx載入這個目錄下面全部.conf結尾的文件。

在vhost中新建b.com.conf文件,用nginx的語法在其中增長一節點:


做用是,將全部請求轉到localhost:8080,監聽80端口,命名爲b.com。

在nginx-1.11.5目錄下打開命令行窗口:

先運行nginx.exe -t,測試一下配置文件,測試成功後運行start nginx.exe啓動nginx,啓動成功後進行測試:

將原來的訪問url開頭的localhost:8080改成b.com,運行後若依然能正常訪問,表明測試成功,說明虛擬主機配置完成了。

由於此次是要在nginx上實現filter的功能,則先將原來的後臺服務端的filter功能刪除掉,

將註冊filter的配置註釋掉:


將下面的邏輯移到nginx中:


其中3個爲固定值,另外兩個由請求的頭來決定,

改成:


將預檢命令的邏輯處理也添加其中,在nginx中直接返回,就不須要轉到應用服務器了。

運行nginx.exe -t,測試一下配置文件。

運行nginx.exe -s reload對nginx進行從新載入。

原來html中base url是經過localhost:8080直接訪問的被調用方的應用服務器,如今將localhost:8080改成b.com,即變成了html中去訪問被調用方的nginx http服務器了。

發送的cookie是被調用方的域名的cookie。在b.com下添加document.cookie='cookie1=xxx'


被調用方 - apache解決方案

先運行nginx.exe -s stop將nginx中止掉,而後刷新b.com的請求,請求失敗,說明nginx被停掉了。接下來進行apache的配置:

與nginx同樣,咱們先進行虛擬主機的配置,進入Apache24/conf目錄下,打開httpd.conf文件,

先打開虛擬主機的相關配置,搜索vhost,將LoadModule...mod_vhost_alias.so註釋打開,

將配置文件Include conf/extra/httpd-vhosts.conf註釋也打開,保存httpd.conf。

找到對應的虛擬主機配置文件,即conf/extra/httpd-vhosts.conf,打開,文件中的每個節點就是一個虛擬主機,將最後一個節點的代碼複製一份並添加到最後,刪掉無用的前兩行,ServerName改成b.com,日誌改成b.com-error.log...。在最後一行增長一個代理,讓它把咱們的請求轉發過去,

ProxyPass / http://localhost:8080/

而後將此配置文件保存。由於此處使用了Proxy模塊,因此需將文件中Proxy模塊也打開,搜一下,將140行

LoadModule proxy_module modules/mod_proxy.so複製代碼

打開,還須要把149行的

LoadModule proxy_http_module modules/mod_proxy_http.so複製代碼

打開,保存文件。

鍵入Apache/bin目錄,雙擊httpd.exe,彈出窗口,Apache啓動成功,刷新下b.com的請求,此時b.com可正常訪問了,表示虛擬主機配置成功了。

來測試一下,刷新下測試用例,看到爲所有失敗,接下來須要在Apache上配置下響應頭,

增長支持跨域的響應頭:

繼續編輯httpd-vhosts.conf文件,在ProxyPass下增長代碼:

Apache的配置比較複雜:


須要將httpd.conf中Headers和Rewrite模塊打開:

搜索headers,將118行打開

LoadModule headers_module modules/mod_headers.so複製代碼

搜索rewrite,將158行打開

LoadModule rewrite_module modules/mod_rewrite.so複製代碼

保存修改後的兩個文件。

將Apache關掉,雙擊重啓,刷新測試用例,此時測試用例所有成功,表示此時的Apache支持跨域了,Apache的配置到此結束。


被調用方 - Spring框架解決方案

以前的方案都和框架無關,好比filter,是每一個web應用都有的。若是採用了Spring框架,那麼解決方案就變得簡單起來,增長相應註解便可,請求也不須要再通過中間的http服務器了。

因此,首先將html中的base url b.com改回爲localhost:8080,修改服務器後臺代碼,在TestController中增長註解,

@CrossOrogin
public class TestController {
複製代碼

保存,

再次刷新測試用例,能夠看到,測試用例所有經過。

@CrossOrogin能夠加在類上面,也能夠加在具體的方法上面。加在類上即表明此類的全部方法都支持跨域;它還能夠進行一些額外的配置,但通常場景是不須要額外配置的。


調用方解決跨域 - 隱藏跨域 - nginx配置

當你沒法修改被調用方的時候,就要在調用方作文章。請求是經由調用方的http服務器的反向代理,轉發到被調用方的服務器的,在瀏覽器上面,看不到任何的跨域請求。

那麼,什麼是反向代理呢?

簡單來講,就是你訪問同一個域名的兩個不一樣url,它們最後會去到兩個不一樣的服務器,咱們經過接下來的測試來理解這個概念:

先看一下反向代理在nginx上是怎樣配置的:

配置以前,先把測試環境還原成不支持跨域調用,

把註解@CrossOrigin刪除掉:

接下來,在

C:\Windows\System32\drivers\etc\hosts文件中增長一個host,

將原127.0.0.1 b.com改成

127.0.0.1 b.com a.com複製代碼

用a.com表示調用方的虛擬主機。

而後,在nginx-1.11.5\conf\vhost中新建配置文件a.com.conf

域名爲a.com,將全部請求轉發到81端口,

加一個代理,把咱們要調用的服務器的地址代理成ajaxserver


將html中的base url改成/ajaxserver

運行start nginx.exe啓動nginx

運行nginx -s reload從新加載配置,訪問a.com,能夠看到3個成功,但getCookie失敗了,

是由於新的域名裏沒有cookie的信息,在a.com下添加document.cookie="cookie1=xxx"

再次刷新,測試用例所有成功,跨域問題獲得瞭解決。

看一下這種隱藏跨域與以前的支持跨域最大不一樣是什麼?

就是咱們調用的base url。

隱藏跨域下面調用的url都是本域的,因此base url處爲相對地址,

而以前支持跨域裏面,base url處寫的必須是絕對地址,這就是最大的不一樣。

瀏覽器看到都是相對地址,都是同一個域的地址,因此不會有任何跨域問題。


調用方解決跨域 - 隱藏跨域 - Apache配置

Apache反向代理配置:

配置的目的就是增長一個虛擬主機,在虛擬主機中把跨域請求作一個代理,

找到Apache的虛擬主機配置文件conf/extra/httpd-vhosts.conf

增長一個節點:


將base url改成ajaxserverapache

保存。將nginx.exe -s stop停掉,啓動Apache服務,

運行a.com,測試成功,

且發現Request URL爲http://a.com/ajaxserverapache/getCookie

Apache反向代理配置完成。


注:以上文章部分整理自慕課網教學視頻:

https://www.imooc.com/video/16591

https://www.imooc.com/video/16592

相關文章
相關標籤/搜索