URL 在 IIRF 中的后续请求中存储在 SCRIPT_NAME 中?

URL being stored in SCRIPT_NAME on subsequent requests in IIRF?

我在 IIS6 上遇到 IIRF(Ionics Isapi 重写过滤器)的问题(虽然在这种情况下不确定是否相关),它似乎在处理初始请求时有效,但在标准刷新(即 F5)不是 CTRL + F5),大多数时候它只会是 404。虽然它看起来是间歇性的。我的重写规则本身看起来是正确的,并且我已经在各种 RegEx 测试仪上测试过它,事实上它在清除缓存刷新时也能正常工作。我不是专家,但它似乎与这样一个事实有关,即在它不起作用的时候,我试图点击的页面的 URL 正在 SCRIPT_NAME HTTP 变量,而不是通过 URL,在这种情况下,它似乎是我想重新写入的路径(尽管就像我说的那样,它是 404,所以它似乎实际上不会去在这些情况下这条路径)。我相信您很快就会发现我实际上只是在进行无扩展 URL 重写。我尝试添加规则以在 SCRIPT_NAME 上重写,但到目前为止还没有这样的运气。

我的配置是:

RewriteLog iirf
RewriteLogLevel 5
RewriteEngine ON 
IterationLimit 5

UrlDecoding OFF

# Rewrite all extensionless URLs to index.html 
RewriteRule ^[^.]*$ /appname/index.html

查看下面的日志 - 这是它不工作的情况。我正在点击 /appname/task/5,但它似乎将其存储在 SCRIPT_NAME 中。奇怪的是,它似乎想要重写的 URL 实际上是我希望它重写的 URL 。同样,这仅适用于后续请求。在第一次请求时,它几乎总是可以毫无问题地重写并且页面加载正常。

Tue Jul 12 10:17:33 -  4432 - Cached: DLL_THREAD_DETACH
Tue Jul 12 10:17:33 -  4432 - Cached: DLL_THREAD_DETACH
Tue Jul 12 10:17:33 -  4432 - HttpFilterProc: SF_NOTIFY_URL_MAP
Tue Jul 12 10:17:33 -  4432 - HttpFilterProc: cfg= 0x01C8CC60
Tue Jul 12 10:17:33 -  4432 - HttpFilterProc: SF_NOTIFY_AUTH_COMPLETE
Tue Jul 12 10:17:33 -  4432 - DoRewrites
Tue Jul 12 10:17:33 -  4432 - GetServerVariable_AutoFree: getting 'QUERY_STRING'
Tue Jul 12 10:17:33 -  4432 - GetServerVariable_AutoFree: 1 bytes
Tue Jul 12 10:17:33 -  4432 - GetServerVariable_AutoFree: result ''
Tue Jul 12 10:17:33 -  4432 - GetHeader_AutoFree: getting 'method'
Tue Jul 12 10:17:33 -  4432 - GetHeader_AutoFree: 4 bytes   ptr:0x000D93A8
Tue Jul 12 10:17:33 -  4432 - GetHeader_AutoFree: 'method' = 'GET'
Tue Jul 12 10:17:33 -  4432 - DoRewrites: Url: '/appname/index.html'
Tue Jul 12 10:17:33 -  4432 - EvaluateRules: depth=0
Tue Jul 12 10:17:33 -  4432 - GetServerVariable: getting 'SCRIPT_NAME'
Tue Jul 12 10:17:33 -  4432 - GetServerVariable: 16 bytes
Tue Jul 12 10:17:33 -  4432 - GetServerVariable: result '/appname/task/5'
Tue Jul 12 10:17:33 -  4432 - EvaluateRules: no RewriteBase
Tue Jul 12 10:17:33 -  4432 - EvaluateRules: Rule 1: pattern: ^[^.]*$  subject: /appname/index.html
Tue Jul 12 10:17:33 -  4432 - EvaluateRules: Rule 1: -1 (No match)
Tue Jul 12 10:17:33 -  4432 - EvaluateRules: returning 0
Tue Jul 12 10:17:33 -  4432 - DoRewrites: No Rewrite

非常感谢任何帮助!

谢谢

我不确定将它存储在 SCRIPT_NAME 变量中的原因是什么,但我已经编写了一个额外的规则来满足它,它为我修复了它:

RewriteEngine ON
IterationLimit 5
UrlDecoding OFF

# Rewrite all extensionless URLs to index.html 
RewriteRule ^[^.]*$ /appname/index.html

# Subsequent requests may store the URL in the SCRIPT_NAME variable for some reason
RewriteCond %{SCRIPT_NAME} ^[^.]*$ # If SCRIPT_NAME variable contains an extensionless URL
RewriteRule .*\S.* /appname/index.html [L] # Rewrite all URLs to index if RewriteCond met

我遇到这个问题已经有一段时间了,为了解决这个问题,我在集成 Windows 身份验证安全网站上 运行ning 了它。我认为问题不仅仅影响请求的 uri。我的猜测是 IIRF 以某种方式缓存了先前请求的指令集,并使用它。

为了测试,首先我确保 HTTP 响应 headers 强制浏览器不缓存任何内容,因此浏览器应该 总是 请求和接收更新的内容.这确实按预期工作。

我让 IIRF 指令通过我可以在其间切换的各种目标脚本文件来解析请求。我发现,在更新和保存 IIRF.ini 指令和 php 文件之后,每个请求,基本上在软刷新 (F5) 之后,都会确实收到更新的 content(IIS 正在解析和提供脚本),但执行的指令是 previous

例如,如果请求通过指令导致合法的 404 错误,那么下一个 URL 请求,无论是否针对现有脚本,也会产生 404 错误。获取新的完整请求(通常是 Ctrl-F5 硬刷新,或第一个请求)实际上会执行 proper/current 指令。

经过一些 header 分析,显示问题的请求似乎具有不同步的服务器变量,首先 运行 通过指令:

  • SCRIPT_NAME 保存当前正在请求的 URL
  • REQUEST_URI 显示了 previous URL requested (唯一的变量与之前的 URL)

这意味着 RewriteRule 指令将使用之前的 request_uri,它不包含正确的 url。这似乎解释了后续请求的 'old' 不正确的最终结果。我添加了以下指令,这似乎至少在基本层面上解决了这个问题:

RewriteCond %{REQUEST_URI}::%{SCRIPT_NAME} !^([^\?]*?)(\?.*)?::$
RewriteRule ^ %{SCRIPT_NAME} [R=301,L,QSA]
  • 第一次检查确保 request_uri 的 pre-querystring 值匹配 script_name 值
  • 301 强制浏览器进行硬刷新,然后应该同步 URLs(并且还会重新发送任何查询字符串)。它应该是第一个指令,其余指令如下。

然而,如果相同的 url 被第二次请求,这将不起作用。在发送硬刷新之前,新保存的指令不会被占用。我还没有找到一种方法来确定 same URL.

的软刷新是否正在解析最新的指令

在我的安全站点上下文中,它似乎也不想处理不包含授权 HTTP header 的请求。每个浏览器都会正确执行登录握手过程,但一旦获得授权,如果浏览器不发送 header,它可能会在不应产生它的请求上导致缓存 401 错误。所以我确定相同的解决方案可以应用于这些请求——只要浏览器没有发送授权就强制刷新 header:

RewriteCond %{REQUEST_URI}::%{SCRIPT_NAME} !^([^\?]*?)(\?.*)?::$ [OR]
RewriteCond %{HTTP_Authorization} !^.+$
RewriteRule ^ %{SCRIPT_NAME} [R=301,L,QSA]

我认为此解决方案解决了上面的 same-url 软刷新问题,因为软刷新似乎没有发送授权 header。实际上,每个请求都变成了硬刷新,确保同步变量和安全内容的 Auth header。

对于误报,如果在指令更改 授权 header发送。安全内容将是最新的,但使用的指令仍将是以前的版本。

对于使用不同但有效的 request_uri 和 script_name 值解析的任何请求(通常这是在第二次迭代中),它也可能不够。一个步骤可能是在第一次迭代匹配时设置环境变量,并且仅在它是指令的第一次迭代时才进行同步检查和重定向。但是IIRF好像不支持[E]修饰符。

简而言之,我认为这描述了问题: 通过 IIRF,对于任何有效的 first 请求迭代,^%{REQUEST_URI}(\?.+)?$ 应该始终匹配%{SCRIPT_NAME},但如果变量在第一次迭代时相同,则会发生无法捕获的 old-directives 解析,除非有一种方法可以检查缓存(当前使用) 针对已保存指令的指令。

无论如何,希望这离确定这个看似缓存的 previous-request-and-directives IIRF 错误的通用解决方法又近了一步。