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