nginx解決跨域問題

一. 產生跨域的緣由

1.瀏覽器限制
2.跨域
3.XHR(XMLHttpRequest)請求

二. 解決思路

解決跨域有多重,在這裏主要講用nginx解決跨域javascript

1.JSONP
2.nginx代理
3.瀏覽器禁止檢查跨域

三. 下載安裝nginx

nginx下載地址html

  • 選擇其中一個版本下載,再解壓便可使用
  • 在nginx目錄下輸入nginx -v,若出現版本號,則安裝成功
  • nginx

四. 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配置的java

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服務
如今能夠測試下接口
測試接口
能夠看出,node服務成功開啓
如今能夠嘗試不開啓nginx服務直接發送ajax請求會出現什麼狀況
(注意:發送ajax請求須要以服務器方式打開網頁,不能以文件形式)
跨域問題
如圖,在5500端口請求3000端口出現了跨域問題,這時候就能夠開啓nginx服務並配置location進行解決node

2.配置nginx進行反向代理解決跨域

反向代理的原理就是講前端的地址和後端的地址用nginx轉發到同一個地址下,如5500端口和3000端口都轉到3003端口下,具體配置以下:jquery

  • 打開nginx目錄下的conf目錄裏面nginx.conf
  • 爲了方便之後測試,咱們將配置分離開來,弄成多個文件
  • 在nginx.conf的http對象的最後加上include ../vhost/test.conf;(注意要最後加上分號)
  • 這樣就能夠在test.conf下單獨配置了

具體的location配置規則以下:
nginx的location配置規則nginx

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開頭的urlgit

  • 如今咱們能夠開啓nginx服務了,在nginx目錄下使用start nginx便可開啓服務

開啓nginx服務

  • 每次修改配置都須要執行nginx -s reload命令才能生效

reload
如今修改前端代碼,將以前請求的接口的端口換爲3003,以下:github

$('#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反向代理
成功ajax

五. 後端配置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請求的端口接口,無需修改前端服務器的地址

最後附上源碼:
nginx解決跨域問題

相關文章
相關標籤/搜索