<menu id="w8yyk"><menu id="w8yyk"></menu></menu>
  • <dd id="w8yyk"><nav id="w8yyk"></nav></dd>
    <menu id="w8yyk"></menu>
    <menu id="w8yyk"><code id="w8yyk"></code></menu>
    <menu id="w8yyk"></menu>
    <xmp id="w8yyk">
    <xmp id="w8yyk"><nav id="w8yyk"></nav>
  • 網站首頁 > 物聯資訊 > 技術分享

    Nginx 配置指令的執行順序(八)

    2016-09-28 00:00:00 廣州睿豐德信息科技有限公司 閱讀
    睿豐德科技 專注RFID識別技術和條碼識別技術與管理軟件的集成項目。質量追溯系統、MES系統、金蝶與條碼系統對接、用友與條碼系統對接

     前面我們詳細討論了 rewriteaccess 和 content 這三個最為常見的 Nginx 請求處理階段,在此過程中,也順便介紹了運行在這三個階段的眾多 Nginx 模塊及其配置指令。同時可以看到,請求處理階段的劃分直接影響到了配置指令的執行順序,熟悉這些階段對于正確配置不同的 Nginx 模塊并實現它們彼此之間的協同工作是非常必要的。所以接下來我們接著討論余下的那些階段。

     

        前面在 (一) 中提到,Nginx 處理請求的過程一共劃分為 11 個階段,按照執行順序依次是 post-readserver-rewritefind-configrewritepost-rewritepreaccessaccesspost-accesstry-filescontent 以及 log.

     

        最先執行的 post-read 階段在 Nginx 讀取并解析完請求頭(request headers)之后就立即開始運行。這個階段像前面介紹過的 rewrite 階段那樣支持 Nginx 模塊注冊處理程序。比如標準模塊 ngx_realip 就在post-read 階段注冊了處理程序,它的功能是迫使 Nginx 認為當前請求的來源地址是指定的某一個請求頭的值。下面這個例子就使用了 ngx_realip 模塊提供的 set_real_ip_from 和 real_ip_header 這兩條配置指令:

        server {
            listen 8080;
     
            set_real_ip_from 127.0.0.1;
            real_ip_header   X-My-IP;
     
            location /test {
                set $addr $remote_addr;
                echo "from: $addr";
            }
        }

    這里的配置是讓 Nginx 把那些來自 127.0.0.1 的所有請求的來源地址,都改寫為請求頭 X-My-IP 所指定的值。同時該例使用了標準內建變量 $remote_addr 來輸出當前請求的來源地址,以確認是否被成功改寫。

     

        首先在本地請求一下這個 /test 接口:

        $ curl -H 'X-My-IP: 1.2.3.4' localhost:8080/test
        from: 1.2.3.4

    這里使用了 curl 工具的 -H 選項指定了額外的 HTTP 請求頭 X-My-IP: 1.2.3.4. 從輸出可以看到,$remote_addr 變量的值確實在 rewrite 階段就已經成為了 X-My-IP 請求頭中指定的值,即 1.2.3.4. 那么 Nginx 究竟是在什么時候改寫了當前請求的來源地址呢?答案是:在 post-read 階段。由于 rewrite 階段的運行遠在 post-read 階段之后,所以當在 location 配置塊中通過 set 配置指令讀取 $remote_addr 內建變量時,讀出的來源地址已經是經過 post-read 階段篡改過的。

     

        如果在請求上例中的 /test 接口時沒有指定 X-My-IP 請求頭,或者提供的 X-My-IP 請求頭的值不是合法的 IP 地址,那么 Nginx 就不會對來源地址進行改寫,例如:

        $ curl localhost:8080/test
        from: 127.0.0.1
     
        $ curl -H 'X-My-IP: abc' localhost:8080/test
        from: 127.0.0.1

    如果從另一臺機器訪問這個 /test 接口,那么即使指定了合法的 X-My-IP 請求頭,也不會觸發 Nginx 對來源地址進行改寫。這是因為上例已經使用 set_real_ip_from 指令規定了來源地址的改寫操作只對那些來自127.0.0.1 的請求生效。這種過濾機制可以避免來自其他不受信任的地址的惡意欺騙。當然,也可以通過set_real_ip_from 指令指定一個 IP 網段(利用 (三) 中介紹過的“CIDR 記法”)。此外,同時配置多個set_real_ip_from 語句也是允許的,這樣可以指定多個受信任的來源地址或地址段。下面是一個例子:

        set_real_ip_from 10.32.10.5;
        set_real_ip_from 127.0.0.0/24;

    有的讀者可能會問,ngx_realip 模塊究竟有什么實際用途呢?為什么我們需要去改寫請求的來源地址呢?答案是:當 Nginx 處理的請求經過了某個 HTTP 代理服務器的轉發時,這個模塊就變得特別有用。當原始的用戶請求經過轉發之后,Nginx 接收到的請求的來源地址無一例外地變成了該代理服務器的 IP 地址,于是 Nginx 以及 Nginx 背后的應用就無法知道原始請求的真實來源。所以,一般我們會在 Nginx 之前的代理服務器中把請求的原始來源地址編碼進某個特殊的 HTTP 請求頭中(例如上例中的 X-My-IP 請求頭),然后再在 Nginx 一側把這個請求頭中編碼的地址恢復出來。這樣 Nginx 中的后續處理階段(包括 Nginx 背后的各種后端應用)就會認為這些請求直接來自那些原始的地址,代理服務器就仿佛不存在一樣。正是因為這個需求,所以 ngx_realip 模塊才需要在第一個處理階段,即 post-read 階段,注冊處理程序,以便盡可能早地改寫請求的來源。

     

        post-read 階段之后便是 server-rewrite 階段。我們曾在 (二) 中簡單提到,當 ngx_rewrite 模塊的配置指令直接書寫在 server 配置塊中時,基本上都是運行在 server-rewrite 階段。下面就來看這樣的一個例子:

        server {
            listen 8080;
     
            location /test {
                set $b "$a, world";
                echo $b;
            }
     
            set $a hello;
        }

    這里,配置語句 set $a hello 直接寫在了 server 配置塊中,因此它就運行在 server-rewrite 階段。而server-rewrite 階段要早于 rewrite 階段運行,因此寫在 location 配置塊中的語句 set $b "$a, world" 便晚于外面的 set $a hello 語句運行。該例的測試結果證明了這一點:

        $ curl localhost:8080/test
        hello, world

    由于 server-rewrite 階段位于 post-read 階段之后,所以 server 配置塊中的 set 指令也就總是運行在ngx_realip 模塊改寫請求的來源地址之后。來看下面這個例子:

        server {
            listen 8080;
     
            set $addr $remote_addr;
     
            set_real_ip_from 127.0.0.1;
            real_ip_header   X-Real-IP;
     
            location /test {
                echo "from: $addr";
            }
        }

    請求 /test 接口的結果如下:

        $ curl -H 'X-Real-IP: 1.2.3.4' localhost:8080/test
        from: 1.2.3.4

    在這個例子中,雖然 set 指令寫在了 ngx_realip 的配置指令之前,但仍然晚于 ngx_realip 模塊執行。所以$addr 變量在 server-rewrite 階段被 set 指令賦值時,從 $remote_addr 變量讀出的來源地址已經是經過改寫過的了。

    RFID管理系統集成商 RFID中間件 條碼系統中間層 物聯網軟件集成
    最近免费观看高清韩国日本大全