nginx修改cookieName配置記錄


前言

通常工作中反向代理需要攜帶上前端請求的cookie,在nginx反向代理中配置proxy_set_header Cookie $http_cookie;,這樣后端就可以接收到瀏覽器上送的cookie了。但是這種方案只是適合前端請求的cookieName就是后端需要的。但是如果cookieName不同,需要進行轉換呢?

背景

最近工作中遇到個問題,系統A和系統B需要進行整合為一個門戶系統(要進行統一認證),A系統沒有使用公司網關,用戶認證是自己開發的web層(實現spring-security filter進行攔截到sso認證),系統B只提供dubbo服務,B的web層是網關,由網關進行用戶認證和鑒權,然后網關調用系統B的dubbo服務。系統A的web層等同系統B的網關。無論是網關還是自己系統的web層,認證都是使用的oauth2流程到公司的sso系統進行統一認證。公司sso是session存放在redis,由sessionId作為redis key,而cookie值就是sessionid的base64編碼,那么可以通過cookie就判斷用戶是否進行了登錄(根據cookie查找到)。

系統A session使用的cookie名稱是mobileSessionId,系統B session使用的cookie名稱是SESSIONID,那么在系統A經過登錄產生的cookie在訪問系統B的時候,可否通過nginx轉換下cookie名稱從而在A系統也可以直接使用呢?經過google,發現nginx的headers-more-nginx-module模塊可以實現。

headers-more-nginx-module模塊在nginx並不自帶,需要進行安裝,下面說下步驟

安裝nginx和headers-more-nginx-module模塊

yum install nginx安裝的nginx是無法進行編譯的,比較麻煩,headers-more-nginx-module模塊安裝需要進行編譯,因此安裝nginx使用源碼安裝

源碼方式安裝nginx

root用戶登錄,當前用戶路徑是/root

下載nginx源碼包wget http://nginx.org/download/nginx-1.17.8.tar.gz

解壓tar -zxvf nginx-1.17.8.tar.gz

進入上步解壓目錄cd /root/nginx-1.17.8

編譯安裝nginx

./configure --prefix=/etc/nginx --with-debug   #nginx安裝到/etc/nginx目錄,安裝debug,方便調試
make
make install
ln -s  /etc/nginx/sbin/nginx /usr/sbin/nginx #軟連,方便使用nginx命令

# --with-debug是安裝nginx的debug模式,出了問題方便查看 http://nginx.org/en/docs/debugging_log.html

安裝headers-more-nginx-module模塊

從https://github.com/openresty/headers-more-nginx-module下載headers-more-nginx-module模塊

./configure --prefix=/etc/nginx \	#安裝模塊到nginx的安裝目錄
     --add-module=/root/headers-more-nginx-module-0.33 \	#headers-more-nginx-module模塊下載解壓目錄
     --with-debug	#安裝nginx debug
make
make install

安裝參考https://github.com/openresty/headers-more-nginx-module

nginx配置修改cookie名稱實戰

啟動nginx:nginx

通過nginx -v只能查看nginx版本,nginx -V可以查看nginx更多版本信息(包含編譯)

查看nginx使用的配置文件nginx -t如下

image-20210307184753473

注意這里有個坑是yum install nginx安裝的nginx默認會使用conf.d目錄下以.conf結尾的文件作為配置,但是源碼編譯安裝nginx方式不會,原因是yum安裝的nginx的nginx.conf內有include /etc/nginx/conf.d/*.conf;,而源碼方式安裝的nginx配置內沒有。由於之前都是使用的yum方式安裝nginx,自定義配置都是放conf.d目錄生效,這次使用源碼方式安裝,放心無論如何不生效,排查后發現這個區別。

創建/etc/nginx/conf.d目錄,修改/etc/nginx/conf/nginx.conf在http模塊配置內增加include /etc/nginx/conf.d/*.conf;,這樣自己放/etc/nginx/conf.d目錄下的配置就可以生效。創建/etc/nginx/conf.d/switchcookie.conf,內容如下:

log_format main
                '[$time_local] - $remote_addr:$remote_port - $remote_user - $upstream_addr $upstream_status $upstream_response_time - '
                '"$request" $status $bytes_sent $request_time '
                '"$http_referer" - "$http_user_agent" '
                '"$http_cookie"';	#nginx日志打印cookie

server {
	access_log  logs/access.log  main;
	error_log  logs/error.log  error;
                
    listen       80;
    server_name  zzz.yhd.com;
    client_max_body_size 50m;
	
    location /api {
        add_header Access-Control-Allow-Origin 'zzz.yhd.com';
        add_header Access-Control-Allow-Credentials 'true';
        add_header Access-Control-Allow-Headers 'Origin, X-Requested-With, Content-Type, Accept';
        add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
        proxy_set_header Host $host;
        proxy_set_header x-real-ip $remote_addr;
        proxy_set_header x-forwarded-for $proxy_add_x_forwarded_for;
        #headers-more-nginx-module模塊--start
        if ($cookie_mobileSessionId) {	#前端上送的cookie中有cookie名稱為mobileSessionId則判斷為true
            more_set_input_headers "Cookie: SESSION=$cookie_mobileSessionId; $http_cookie";
            #more_set_input_headers "Cookie: SESSION=$cookie_mobileSessionId";
        }
        #headers-more-nginx-module模塊--end
        proxy_pass http://ares.zzz.com/api;
        #proxy_redirect off;
        proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504 http_404;
    }
    
}

這個配置就是瀏覽器訪問http://zzz.yhd.com/api(Cookie:mobileSessionId=ZDE4NzI3YTItZTMxNy00YWRlLTgwZGItNjUwNjYwMjkxZTgx),從而反向代理到http://ares.zzz.com/api(Cookie:SESSIONID=ZDE4NzI3YTItZTMxNy00YWRlLTgwZGItNjUwNjYwMjkxZTgx),這樣就把cookie名稱通過nginx配置轉換了。

配置說明如下:

$cookie_mobileSessionId是說明前端上送的cookie名稱是mobileSessionId,如果cookie名稱是SESSION,那么就用$cookie_SESSIONID

if ($cookie_mobileSessionId)說明前端上送的cookie中有名稱mobileSessionId,如果上送了則執行more_set_input_headers邏輯

more_set_input_headers "Cookie: SESSION=$cookie_mobileSessionId; $http_cookie";反向代理到ares.zzz.com增加cookie名稱為SESSIONID值為mobileSessionId的值,同時把前端請求的cookie也轉發到ares.zzz.com。

more_set_input_headers "Cookie: SESSION=$cookie_mobileSessionId"反向代理到ares.zzz.com增加cookie名稱為SESSIONID值為mobileSessionId的值,不攜帶前端請求上送的cookie。

$cookie_NAME #客戶端請求Header頭中的cookie變量,前綴"$cookie_"加上cookie名稱的變量,該變量的值即為cookie名稱的值
$cookie_COOKIE 客戶端請求中COOKIE頭域的值
$http_cookie 客戶端cookie信息

實戰截圖如下

通過nginx這樣配置,請求測試正常

image-20210307192215472

域名zzz.yhd.com前端所在服務器的nginx日志顯示如下

image-20210307192256071

域名ares.zzz.com前端所在服務器nginx日志顯示如下

image-20210307192346122

流程圖

image-20210307214952715

總結

通過這種方式,在整合A和B兩個系統時候,無需改動B系統(走的網關),這樣就統一對系統A和B進行了認證。否則系統B要開發下自己的web層,這樣減少了系統B開發web層的工時,提升了效率。

代理到容器域名問題

在做修改cookieName的時候,域名反向代理到虛擬機環境的域名是正常,但是代理到容器域名就不行,經過排除和容器組同時溝通得知,容器的域名是通過ingress進行反向代理的,接收到的域名必須是容器域名,否則不識別。因此我的配置內的 proxy_set_header Host $host; 在反向代理到容器域名時候,ingress接收到的是http://zzz.yhd.com,因此在proxy_pass到容器域名時候,必須要改為proxy_set_header Host "http://ares.zzz.com"; 這樣容器ingress接收到的域名才是配置在容器內的域名,才可以正常反向代理到內部容器。

后續又遇到同事開發釘釘小程序,外網請求內部服務反向代理到內部服務容器域名,也是此問題,改為proxy_set_header Host "http://ares.zzz.com";解決。

nginx常用命令總結

nginx啟動 nginx

nginx停止 nginx -s quit (優雅停止) nginx -s stop(硬停止)

重新加載 nginx -s reload 修改了配置需要執行此命令

顯示nginx版本 nginx -v

顯示nginx版本(詳細) nginx -V

顯示nginx使用的配置 nginx -t

參考

https://blog.csdn.net/chunyuan314/article/details/81910084

https://lanjingling.github.io/2016/03/14/nginx-access-log/


免責聲明!

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



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