windows環境下 nginx+iis 反向代理解決跨域問題


項目基本完成,是時候花點時間整理一下最近的姿勢了

1 什么是跨域?

網上對於跨域的概念會有大篇幅的文章去解釋,似乎有點玄乎,初學者很容易對這個概念產生恐懼,跨域其實很簡單,其實只要知道一點,無法跨域訪問的本質原因其實是瀏覽器為了安全對前端腳本(一般腳本都是js)請求的一種限制,注意是瀏覽器的限制,而不是服務器的限制

即同一域下的js只能請求同一域下的接口,何為同一域?何為不同域?端口號相同且請求協議相同且主機名相同即為同一域,三個條件任意一條不滿足都是跨域訪問

下面實戰一個簡單的栗子:

如圖,我們在本地IIS新建一個端口號為8081的web1,地址為http://localhost:8081,再新建一個端口號為8083的web2,地址為http://localhost:8083

然后在web1放一個代碼如下的靜態html,用ajax去請求web1下面的接口

web2里面為打包發布的.net webapi,代碼如下

   public class HomeController : ApiController
    {
        // GET api/home/get
        [HttpGet]
        public IEnumerable<string> Get()
        {
            return new string[] { "value1", "value2" };
        }
    }

一切就緒后我們http://localhost:8081打開web1,瀏覽器調試發現會有如下報錯

由於端口號不同,XMLHttpruqest對象無法請求http://localhost:8083的數據,這就是端口號不同導致的Ajax無法跨域請求。跨域其實就這么簡單

2 那么如何解決跨域問題呢?

網上關跨域問題的解決方案有多種多樣,我大概整理了一下大概有這么多跨域解決方案

1、 通過jsonp跨域
2、 document.domain + iframe跨域
3、 location.hash + iframe
4、 window.name + iframe跨域
5、 postMessage跨域
6、 跨域資源共享(CORS)
7、 nginx代理跨域
8、 nodejs中間件代理跨域
9、 WebSocket協議跨域

上述方案前6種方案都有大大小小的問題:

比如方案1中的jsonp實現跨域的缺點:只能實現get一種請求,傳輸數據有限制。又比如方案6中的CORS跨域雖然支持Post請求,但是必須要所跨域的服務器需要實現Cors,而且還有少量瀏覽器不兼容,上述8,9兩種方案可能是相對比較新的解決方案,我這邊也沒深入了解學習過,有興趣的朋友可以自行百度學習一下,在這里主要分享一下關於Nginx的實戰總結

3 Nginx反向代理解決跨域問題

什么是反向代理?什么是正向代理?我之前有文章寫過這概念,這里就不過多的解釋這個概念了,可以參考文章https://www.cnblogs.com/ruanraun/p/agent.html

3.1 ngnix安裝配置

首先去官網下載 ngnix http://nginx.org/en/download.html 

解壓安裝包后發現如下目錄,不要急着點擊nginx.exe

cmd打開命令提示符,cd命令定位到當前目錄(還有一種快捷的定位到當前目錄的方法:打開到要定位的目錄,Shift+鼠標右鍵 選擇此處打開命令提示窗口,不過win10安裝了PowerShell的好像就沒有這個選項,那就老老實實用命令定位到當前目錄了,不要用PowerShell)

定位到上圖nginx的目錄之后,用start nginx命令啟動nginx.exe

然后輸入tasklist /fi "imagename eq nginx.exe" 檢查程序是否運行成功,如圖即為運行成功

如果沒有運行成功一般都是80端口被占用,去logs目錄下查看日志

兩種解決方案:

1,禁用占用80端口的程序,輸入命令netstat -ano |more,查看到pid為4的程序占用了改端口,禁用掉這個程序,個人覺得這個方法不太靠譜,因為你可能不知道被禁用程序的作用,有時可能是系統程序,也有可能是部署的其他程序,所以直接禁用可能會引起其他問題,除非非要部署到80端口且知道80端口被占用程序的作用的情況下使用這個解決方案

2,改nginx配置,使用其他端口,打開conf文件下的nginx.conf文件,把里面的80端口改成其他端口,我這里用的是8082端口

修改完配置完成后保存,然后到之前的命令提示符窗口輸入:nginx -s reload 重啟nginx,記住每次修改完配置后都要重啟nginx

然后訪問http://localhost:8082,出現下面界面說明就配置OK啦

3,繼續配置nginx.conf文件實現跨域

 

配置說明:

1.由配置信息可知,我們讓nginx監聽localhost的8082端口,web1與web2的訪問都是經過localhost的8082端口進行訪問。

2.我們特殊配置了一個“/apis”目錄的訪問,並且對url執行了重寫,最后使以“/apis”開頭的地址都轉到“http://localhost:8081”進行處理。

3.rewrite  ^/apis/(.*)$ /$1 break; 

代表重寫攔截進來的請求,並且只能對域名后邊以“/apis”開頭的起作用,例如www.a.com/apis/msg?x=1重寫。只對/apis重寫。

  rewrite后面的參數是一個簡單的正則 ^/apis/(.*)$ ,$1代表正則中的第一個(),$2代表第二個()的值,以此類推。

  break代表匹配一個之后停止匹配。

全部配置文件如下

#user  nobody;
worker_processes  1;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       mime.types;
    default_type  application/octet-stream;

    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';

    #access_log  logs/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    #gzip  on;

    server {
        listen       8082;
        server_name  localhost;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
            proxy_pass http://localhost:8081;
            proxy_redirect default;
        }

        location /apis { #添加訪問目錄為/apis的代理配置
            rewrite  ^/apis/(.*)$ /$1 break;
            proxy_pass   http://localhost:8083;
        }

        #error_page  404              /404.html;

        # redirect server error pages to the static page /50x.html
        #
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }

        # proxy the PHP scripts to Apache listening on 127.0.0.1
        #
        #location ~ \.php$ {
        #    proxy_pass   http://127.0.0.1;
        #}

        # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
        #
        #location ~ \.php$ {
        #    root           html;
        #    fastcgi_pass   127.0.0.1:9000;
        #    fastcgi_index  index.php;
        #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
        #    include        fastcgi_params;
        #}

        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        #location ~ /\.ht {
        #    deny  all;
        #}
    }


    # another virtual host using mix of IP-, name-, and port-based configuration
    #
    #server {
    #    listen       8000;
    #    listen       somename:8082;
    #    server_name  somename  alias  another.alias;

    #    location / {
    #        root   html;
    #        index  index.html index.htm;
    #    }
    #}


    # HTTPS server
    #
    #server {
    #    listen       443 ssl;
    #    server_name  localhost;

    #    ssl_certificate      cert.pem;
    #    ssl_certificate_key  cert.key;

    #    ssl_session_cache    shared:SSL:1m;
    #    ssl_session_timeout  5m;

    #    ssl_ciphers  HIGH:!aNULL:!MD5;
    #    ssl_prefer_server_ciphers  on;

    #    location / {
    #        root   html;
    #        index  index.html index.htm;
    #    }
    #}

}

還有一最后一步就是修改web1下面的靜態文件代碼,將請求url改成/apis/api/Home/Get

 最后重啟nginx,訪問http://localhost:8082,有時可能會有緩存問題顯示之前的歡迎界面用Ctrl+F5刷新一下就好了,如下圖:

我們看到http://localhost:8082顯示了web1的界面,並且正常輸web2接口返回的數據,是不是換了個思維解決了跨域的問題,我們最終訪問的地址時間是nginx代理的http://localhost:8082,這也就是所說的反向代理,訪問http://localhost:8082的客戶端並不知道用戶界面實際是放在http://localhost:8081端口的web1下,接口程序放在http://localhost:8083端口的web2下。

4 總結

反向代理不僅僅可以解決跨域問題,還有很多好處,大型項目中前端文件和接口程序完全可以發布到不同的服務器中,使用反向代理技術,前后端各自維護自己的服務器,接口程序還可以供不同平台使用.......

nginx十分強大,大佬們都在使用:中國大陸使用nginx網站用戶有:百度、京東新浪網易騰訊淘寶等。

 


免責聲明!

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



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