问题的提出:最近单位遇到一个需求,单位a和单位b,都经过专线链接到我单位,单位b提出须要访问单位a网络中的一个网站应用,原本很简单问题,只须要我单位中一台能够访问两边网络的服务器上,架设nginx就能够解决该问题,事实上,我天真了!html
(ps:本文仅针对对nginx反向代理有必定了解的朋友,如不了解请自行百度)前端
问题出如今这个网站应用上,他们使用了cas架构,在系统登陆的url地址和应用的地址不在一块儿,以下:nginx
当使用系统的地址访问时,他跳转到下面的位置,显示了登陆页面:编程
当登陆系统后,又跳转回192.168.20.150这个地址上。centos
查了一下cas,应该是用于登陆权限管理的。跨域
经过fiddle跟踪,发如今使用http://192.168.20.164登陆时,返回了以下信息浏览器
红线标出了,浏览器下次跳转的url,继续跳转,返回:服务器
继续跳,返回:cookie
到这里,再跳转到index.aspx就进入系统了。网络
是否是有点晕!总结一下:
进入系统,一共进行了三次跳转,系统的登陆首页在192.168.20.164上面,点击登陆成功后,就跳转到192.168.20.150上面去。
能够看出192.168.20.164是一个管理登陆的服务器,系统的真实服务器在192.168.20.150上面。
好了,大致状况清楚了,但问题是如何实现咱们的需求呢??
一、经过网络方式,开通两边的网络,这样确定应该是能够,但太暴力了,也不容许,不现实,pass掉。
二、在中间服务器,使用nginx反向代理,但常规的方式,显然知足不了当前的状况,若是浏览器根据响应返回的location跳转,就会访问不到了,只能看如何在响应头返回前端浏览器前,更改掉Location,让它继续指向咱们本身的nginx服务器地址。
因此,我安装一个台新的centos服务器在192.168.253.155上面,安装nginx 1.9.9,由于须要改变响应头中的Location值,需额外安装ngx_headers_more模块。
在《nginx替换响应头(重点:如何在替换时加上if判断)》这篇文章中有详细的介绍。
nginx.conf主要配置以下:
map $upstream_http_Location $location{
~http://192.168.20.150/(?<param>.*) $param;
default $upstream_http_Location;
}
... ...
server {
listen 80;
server_name localhost;
location /xt/ {
set $qz http://192.168.253.155/;
more_set_headers -s '302' 'Location:$qz$location';
add_header Cache-Control 'no-cache';
add_header Cache-Control 'no-store';
sub_filter '/smportal-cas/' '/xt/smportal-cas/';
sub_filter_once off;
proxy_pass http://192.168.20.164:XXXX/;
}
location / {
... ...
proxy_pass http://192.168.20.150/;
}
... ...
最上面的map用于将登陆页面返回响应头中Location为的内容映射到变量$location中去,咱们能够看到,在192.168.20.164上登陆成功后,首先就跳转到http://192.168.20.150/xxx/xxx.aspx?ticket=xxxxxx,以下图:
这时咱们通~http://192.168.20.150/(?<param>.*) $param;取出150/后面的内容(由于每次后面的内容会不一样)赋到$location中。
(注:(?<xxx> xxxx)是nginx中经过正则取值到变量的方法,此处首先赋值给了$param,而后经过map映射到$location。
至于为何不用$upstream_http_Location直接取值,用if判断呢?前面推荐的那篇文章写的很清楚。)
接下来配置,将http://192.168.253.155/xt/的访问代理到http://192.168.20.164上面,让用户能够访问登陆页面。
其中
set $qz http://192.168.253.155/; #设置变量$qz为咱们本身的地址
more_set_headers -s '302' 'Location:$qz$location'; #将$qz和$location(保存着刚才取到需跳转url的后面路径和参数部分)拼接成指向咱们本身nginx的地址,即替换原先url中http://192.168.20.150为http://192.168.253.155
最后配置http://192.168.253.155/的访问代理到http://192.168.20.150上面去,即完成了本次的任务。
(ps: sub_filter的部分,是由于在登陆页面中有很js,包括登陆按钮提交时的url都使用了绝对的地址,因此须要在返回页面到前端前替换掉这些url,增长咱们前辍/xt/,这样访问才没有问题。
其实,实际状况中, 有不少的限制,好比单位b访问我单位的nginx服务器时,因为中间有网络设备很差调整,限制访问端口只能用80,而不能增长其它端口,因此配置只能使用子路径来区分多代理,原本能够用多端口就不用sub_filter替换内容了。
在实验的过程当中,也尝试过用\代理登陆的192.168.20.164服务器,用子路径\xt代理系统服务器,最后引出了cookie的设置问题,虽最终没这样设,但发现nginx能够设置cookie的path,以保证代理时路径改变,cookie做对应的调整,特在此备注一下:
proxy_cookie_path / /xt/;#将cookie的path的/映射为 /xt/
感受nginx真的很方便,原先为了实现反向代理、跨域,但是用编程实现的,唉。
)