一. 產生跨域的原因
1.瀏覽器限制
2.跨域
3.XHR(XMLHttpRequest)請求
二. 解決思路解決跨域有多重,在這裡主要講用nginx解決跨域
1.JSONP
2.nginx代理
3.瀏覽器禁止檢查跨域
三. 下載安裝nginx選擇其中一個版本下載,再解壓即可使用在nginx目錄下輸入nginx -v,若出現版本號,則安裝成功四. nginx反向代理解決跨域(客戶端解決跨域)
1.我們使用jquery的ajax傳送請求,node開啟後臺服務
前端程式碼:
利用jQuery的ajax api傳送請求
<button id="getOK">傳送請求OK(客戶端解決跨域問題)</button> <button id="getNO">傳送請求NO(客戶端解決跨域問題)</button> <script> $(document).ready(function () { $('#getOK').click(function () { $.ajax({ url:'http://localhost:3000/ok', success:function(res) { console.log("success",res) }, error:function(err) { console.log('fail',err) } }) }) $('#getNO').click(function () { $.ajax({ url:'http://localhost:3000/no', success:function(res) { console.log("success",res) }, error:function(err) { console.log('fail',err) } }) }) }) </script>
後端程式碼:
利用node的express框架開啟服務,並根據url返回json格式的資料,
設定這麼多介面的目的是為了後面匹配nginx的location配置的
const express = require('express')const cookieParser = require('cookie-parser')var app = express()var router = express.Router()router.get('/ok',function (req,res) { res.json({ code:200, msg:"isOK" }) })router.get('/ok/son',function (req,res) { res.json({ code:200, msg:"isOKSon" }) })router.get('/ok2',function (req,res) { res.json({ code:200, msg:"isOK2" }) })router.get('/no',function (req,res) { res.json({ code:200, msg:"isNO" }) })router.get('/no/son',function (req,res) { res.json({ code:200, msg:"isNOSON" }) })router.get('/no/son2',function (req,res) { res.json({ code:200, msg:"isNOSON2" }) })app.use(router)app.use(cookieParser)app.listen(3000,function () { console.log('listen in 3000')})
然後開啟node服務
現在可以測試下介面
可以看出,node服務成功開啟
現在可以嘗試不開啟nginx服務直接傳送ajax請求會出現什麼情況
(注意:傳送ajax請求需要以伺服器方式開啟網頁,不能以檔案形式)
如圖,在5500埠請求3000端口出現了跨域問題,這時候就可以開啟nginx服務並配置location進行解決
2.配置nginx進行反向代理解決跨域
開啟nginx目錄下的conf目錄裡面nginx.conf為了方便以後測試,我們將配置分離開來,弄成多個檔案在nginx.conf的http物件的最後加上include ../vhost/test.conf;(注意要最後加上分號)這樣就可以在test.conf下單獨配置了具體的location配置規則如下:
server{ listen 3003; server_name localhost; ## = /表示精確匹配路徑為/的url,真實訪問為http://localhost:5500 location = / { proxy_pass http://localhost:5500; } ## /no 表示以/no開頭的url,包括/no1,no/son,或者no/son/grandson ## 真實訪問為http://localhost:5500/no開頭的url ## 若 proxy_pass最後為/ 如http://localhost:3000/;匹配/no/son,則真實匹配為http://localhost:3000/son location /no { proxy_pass http://localhost:3000; } ## /ok/表示精確匹配以ok開頭的url,/ok2是匹配不到的,/ok/son則可以 location /ok/ { proxy_pass http://localhost:3000; }}
上面程式碼的意思是將localhost:3003轉發為location:5500,也就是說現在訪問localhost:3003實際上是訪問location:5500,而訪問localhost:3003/no則是訪問localhost:3000,並以no開頭的url
每次修改配置都需要執行nginx -s reload命令才能生效現在修改前端程式碼,將之前請求的介面的埠換為3003,如下:
$('#getOK').click(function () { $.ajax({ url:'http://localhost:3003/ok', success:function(res) { console.log("success",res) }, error:function(err) { console.log('fail',err) } }) })在瀏覽器訪問的也不算location:5500,而是localhost:3003了,再次傳送請求也不會出現跨域問題了,因為他們都是同一個域了,這就是nginx反向代理
五. 後端配置nginx解決跨域(服務端解決跨域)
1. 依舊是ajax+node
這是前端程式碼
$(document).ready(function () { $('#get').click(function () { $.ajax({ url:'http://localhost:3002/ok', // 帶cookies的請求 xhrFields:{ withCredentials:true }, success:function(res) { console.log("success",res) }, error:function(err) { console.log('fail',err) } }) }) })後端程式碼同前面
還有nginx配置如下:
server{ listen 3002; server_name localhost; location /ok { proxy_pass http://localhost:3000; # 指定允許跨域的方法,*代表所有 add_header Access-Control-Allow-Methods *; # 預檢命令的快取,如果不快取每次會發送兩次請求 add_header Access-Control-Max-Age 3600; # 帶cookie請求需要加上這個欄位,並設定為true add_header Access-Control-Allow-Credentials true; # 表示允許這個域跨域呼叫(客戶端傳送請求的域名和埠) # $http_origin動態獲取請求客戶端請求的域 不用*的原因是帶cookie的請求不支援*號 add_header Access-Control-Allow-Origin $http_origin; # 表示請求頭的欄位 動態獲取 add_header Access-Control-Allow-Headers $http_access_control_request_headers; # OPTIONS預檢命令,預檢命令通過時才傳送請求 # 檢查請求的型別是不是預檢命令 if ($request_method = OPTIONS){ return 200; } }}傳送預檢命令的是非簡單請求,具體可以看慕課網ajax跨域完全講解
實際上不是非簡單請求的且不帶cookie只需2個欄位即可解決跨域
add_header Access-Control-Allow-Methods *;
add_header Access-Control-Allow-Origin $http_origin;
這時只需改ajax請求的埠介面,無需修改前端伺服器的地址
喜歡對你有幫助的話記得加個關注不迷路哦