在 web.config 中使用 ExecuteURL 作为 404 处理程序将绕过 URL 重写(即.. outboundRules),而使用其他 responseModes 则不会

Using ExecuteURL as 404 handler in web.config will bypass URL Rewrite (ie.. outboundRules) while using other responseModes won't

我在 web.config 中有以下规则,旨在使用 securehttpOnly 识别和重写出站会话 cookie旗帜:

<rewrite>
    <outboundRules>
        <preConditions>
            <preCondition name="MatchSessionCookies">
                <add input="{RESPONSE_SET_COOKIE}" pattern="." />
            </preCondition>
        </preConditions>

        <rule preCondition="MatchSessionCookies" name="SecureSessionCookies" enabled="true">
            <match serverVariable="RESPONSE_SET_COOKIE" pattern="^(.*sess.*)=(.+)$" />
            <action type="Rewrite" value="{R:1}={R:2}; httpOnly; secure" />
        </rule>
    </outboundRules>
</rewrite>

这会按预期工作,直到 httpErrors 发挥作用:

<httpErrors>
    <remove statusCode="404" subStatusCode="-1" />
    <error statusCode="404" prefixLanguageFilePath="" path="/path/to/404.aspx" responseMode="ExecuteURL" />
</httpErrors>

因此,当访问 /a-page-that-exists.aspx 时,写出的出站 ASPSESSIONID cookie 被 securehttpOnly 成功重写旗帜。

Request URL: /a-page-that-exists.aspx
Status Code: 200 OK

Set-Cookie: ASPSESSIONIDABCDEFG=...; path=/; httpOnly; secure

访问 /a-page-that-does-NOT-exist.aspx 时出现问题。看来 [404] 请求在内部 "routed" 到 ExecuteURL 路径,我的 URL 重写规则被完全绕过。

Request URL: /a-page-that-does-NOT-exist.aspx
Status Code: 200 OK

Set-Cookie: ASPSESSIONIDABCDEFG=...; path=/

关于如何修改我的出站重写规则以便它们可以在被交给我的 404 处理程序之前应用于 [404] 请求的任何想法?

好吧,看起来我们必须凑合使用 URL 重写版本的 IIS <httpErrors /> 处理程序,但它有效:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <!-- Remove existing 404 handler -->
        <httpErrors>
            <remove statusCode="404" subStatusCode="-1" />
        </httpErrors>

        <rewrite>
            <outboundRules>
                <preConditions>
                    <preCondition name="MatchSessionCookies">
                        <add input="{RESPONSE_SET_COOKIE}" pattern="." />
                    </preCondition>
                </preConditions>

                <!-- Does NOT work with ExecuteURL 404 handler -->
                <rule preCondition="MatchSessionCookies" name="SecureSessionCookies" enabled="true">
                    <match serverVariable="RESPONSE_SET_COOKIE" pattern="^(gsm|.*sess.*)=(.+)$" />
                    <action type="Rewrite" value="{R:1}={R:2}; httpOnly; secure" />
                </rule>
            </outboundRules>
            <rules>
                <!-- Re-implement ExecuteURL 404 handler as URL Rewrite -->
                <rule name="Handle404" stopProcessing="true">
                    <match url=".*" />
                    <conditions logicalGrouping="MatchAny">
                        <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
                    </conditions>
                    <action type="Rewrite" url="/path/to/404.aspx?404;{PreserveSchema:{HTTPS}}{HTTP_HOST}{UNENCODED_URL}" />
                </rule>
            </rules>
            <rewriteMaps>
                <!--  -->
                <rewriteMap name="PreserveSchema" defaultValue="OFF">
                    <add key="ON" value="https://" />
                    <add key="OFF" value="http://" />
                </rewriteMap>
            </rewriteMaps>
        </rewrite>
    </system.webServer>
</configuration>

响应:

Request URL: /a-page-that-does-NOT-exist.aspx
Status Code: 200 OK

Set-Cookie: ASPSESSIONIDABCDEFG=...; path=/; httpOnly; secure