我有一个后端应用程序位于受 SSO 保护的反向代理后面。成功验证后,SSO 会导出包含用户 ID 的 HTTP 标头。我需要将此 uid 和其他数据传递给将对所有内容进行签名的程序。
工作原理如下:
- 使用 RewriteMap 定义脚本
- 使用 SSO 导出的标头值设置环境变量
- 调用脚本,获取返回的值并将其附加到环境变量中
- 检查环境变量并使用这些值创建 cookie
然后,最后的 RewriteRule 指令会将流量传递给后端应用程序,问题是,一旦我使用 P 标志设置 RewriteRule,所有上述变量影响都不再起作用。
问题:在代理所有流量之前,如何设法执行所有指令并创建 cookie,以便我的 cookie 可在我的后端应用程序中使用?
RewriteMap cookiemap prg:/dir/cookieSign.py
RewriteRule ^ - [env=LLNGUID:%{HTTP:Test}]
RewriteCond ${cookiemap:%{REMOTE_ADDR}-%{ENV:LLNGUID}} ^(.*)\s(.*)\s(.*)\s([a-z]+)$
RewriteRule ^ - [E=SIGNATURE:%1,E=SETTIME:%2,E=SETIP:%3,E=UIDSCRIPT:%4]
RewriteCond "%{ENV:SIGNATURE}" "!^$"
RewriteCond "%{ENV:SETTIME}" "!^$"
RewriteCond "%{ENV:SETIP}" "!^$"
RewriteCond "%{ENV:UIDSCRIPT}" "!^$"
RewriteRule ^ - [CO=MY_COOKIE:userid=%{ENV:UIDSCRIPT}&sign=%{ENV:SIGNATURE}&time=%{ENV:SETTIME}&ip=%{ENV:SETIP}:.test.ltd:86400:/:true:true]
RewriteRule "^(.*)$" "http://127.0.0.1:8080$1" [P,L]
谢谢 :)
答案1
问题不在于执行顺序 - 指令按照显示的顺序执行 - 而是变量范围和 cookie 设置的问题。
您在此处设置的环境变量将无法用于目标服务器,因为这是一个不同的范围。
您正在“设置”的 cookie 将无法在当前请求中供您的脚本使用。设置 cookie(例如使用标志CO
)会Set-Cookie
在 HTTP 上设置 HTTP 响应标头回复返回到客户端/浏览器。cookie 仅在下一个当浏览器(希望)返回Cookie
HTTP要求標軸。
如果你想将此信息发送到你的后端服务器当前的请求,那么您需要使用不同的方法。也许是代理请求上的查询字符串?
例如:
RewriteMap cookiemap prg:/dir/cookieSign.py
RewriteRule ^ - [env=LLNGUID:%{HTTP:Test}]
RewriteCond ${cookiemap:%{REMOTE_ADDR}-%{ENV:LLNGUID}} ^([^\s]+)\s([^\s]+)\s([^\s]+)\s([a-z]+)$
RewriteRule ^ - [E=SIGNATURE:%1,E=SETTIME:%2,E=SETIP:%3,E=UIDSCRIPT:%4]
RewriteCond %{ENV:SIGNATURE} .
RewriteCond %{ENV:SETTIME} .
RewriteCond %{ENV:SETIP} .
RewriteCond %{ENV:UIDSCRIPT} .
RewriteRule ^ - [ENV=MY_QUERY:userid=%{ENV:UIDSCRIPT}&sign=%{ENV:SIGNATURE}&time=%{ENV:SETTIME}&ip=%{ENV:SETIP}]
RewriteRule (.*) http://127.0.0.1:8080$1?%{ENV:MY_QUERY} [P]
笔记:
- 将与 rewritemap 的输出匹配的正则表达式更改为使用
[^\s]+
而不是.*
避免不必要的回溯。 - 不需要将所有参数括在引号中,除非它们包含空格。
- 与其检查是否为空(
"!^$"
),不如检查它是否为某物, IE.
。 L
使用标志时不需要该标志P
(它是隐含的)。
答案2
感谢@MrWhite 的详细回复,与此同时,我找到了一个似乎可行的解决方案。我保留了上述所有配置,但我没有将其保留在 VHOST 配置中,而是在 VHOST 标签内添加了一个位置标签:
<VirtualHost _default_:443>
#
# Some conf here
#
<LocationMatch "^/*">
RewriteRule ^ - [env=LLNGUID:%{HTTP:Test}]
RewriteCond ${cookiemap:%{REMOTE_ADDR}-%{ENV:LLNGUID}} ^(.*)\s(.*)\s(.*)\s([a-z]+)$
RewriteRule ^ - [E=SIGNATURE:%1,E=SETTIME:%2,E=SETIP:%3,E=UIDSCRIPT:%4]
RewriteCond "%{ENV:SIGNATURE}" "!^$"
RewriteCond "%{ENV:SETTIME}" "!^$"
RewriteCond "%{ENV:SETIP}" "!^$"
RewriteCond "%{ENV:UIDSCRIPT}" "!^$"
RewriteRule ^ - [CO=MY_COOKIE:userid=%{ENV:UIDSCRIPT}&sign=%{ENV:SIGNATURE}&time=%{ENV:SETTIME}&expires=480&ip=%{ENV:SETIP}:.domain.ltd:86400:/:true:true]
RewriteRule "^(.*)$" "http://127.0.0.1:8080%{REQUEST_URI}" [P,L]
</LocationMatch>
</VirtualHost>
通过此配置,cookie 已创建并可供我的后端应用程序使用。我会纠正您在评论中指出的问题。