0

我在 IIS6 上遇到 IIRF(Ionics Isapi 重写过滤器)问题(尽管在这种情况下不确定是否相关),它似乎正在处理初始请求,但在标准刷新时(即 F5 不是 CTRL + F5) ,大多数时候它只会 404。虽然它看起来是间歇性的。我的重写规则本身似乎是正确的,并且我已经在各种 RegEx 测试仪上对其进行了测试,并且它在清除缓存刷新时确实可以正常工作。我不是专家,但这似乎与以下事实有关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

任何帮助深表感谢!

谢谢

4

2 回答 2

0

我不确定它被存储在 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
于 2016-08-01T10:23:33.960 回答
0

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

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

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

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

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

  • SCRIPT_NAME保存当前请求的 URL
  • REQUEST_URI显示之前请求的 URL(具有之前 URL 的唯一变量)

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

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

但是,如果第二次请求相同的 url,这将不起作用。在发送硬刷新之前,新保存的指令不会占用。我还没有找到一种方法来确定是否在软刷新同一URL 时解析最新指令。

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

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

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

对于误报,如果在指令更改发送Authorization 标头在软刷新上请求相同的 url,则理论上此解决方案可能是不够的。安全内容将是最新的,但使用的指令仍将是以前的版本。

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

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

无论如何,希望这更接近于为这个看似缓存的先前请求和指令 IIRF 错误确定通用解决方法。

于 2017-03-06T17:47:50.720 回答