web-dev-qa-db-ja.com

ASP.NET MVC、URLルーティング:最大パス(URL)の長さ

シナリオ

古き良きクエリ文字列のURL構造を使用したアプリケーションがあります。

?x=1&y=2&z=3&a=4&b=5&c=6

そしてそれをパス構造に変更しました:

/x/1/y/2/z/3/a/4/b/5/c/6

ASP.NET MVCと(当然)ASP.NETルーティングを使用しています。

問題

問題は、パラメーターが動的であり、(理論的には)対応する必要があるパラメーターの量に制限がないことです。

これは、次の列車にぶつかるまで大丈夫です。

HTTPエラー400.0-不正な要求ASP.NETはURLで無効な文字を検出しました。

URLが特定の長さを超えると、IISはこのエラーをスローします。

ニッティ・グリッティ

私たちが見つけたものは次のとおりです。

これはIIS問題ではありません

IISには最大パス長の制限がありますが、上記のエラーはこれではありません。

Dot iis dot netを学ぶリクエストフィルタリングセクション「リクエスト制限に基づくフィルター」の使用方法

IISにとってパスが長すぎる場合、400.0ではなく404.14がスローされます。

また、IIS最大パス(およびクエリ)長さは構成可能です:

<requestLimits


   maxAllowedContentLength="30000000"


   maxUrl="260"


   maxQueryString="25" 


              />

これはASP.NETの問題です

いくつかの周りをつついた後:

IISフォーラムスレッド:ASP.NET 2.0の最大URL長さ? http://forums.iis.net/t/1105360.aspx

これはASP.NET(実際には.NETの)問題であることがわかりました。

問題の核心は、私が知る限り、ASP.NETは260文字を超えるパスを処理できないことです。

これがフィル・ザ・ハーク自身によって確認されているというinの中の釘:

スタックオーバーフローASP.NET url MAX_PATH制限質問ID 265251

質問

それでは、質問は何ですか?

問題は、これはどの程度の制限ですか?

私のアプリの場合、これは取引キラーです。ほとんどのアプリでは、おそらく問題ではありません。

開示はどうですか? ASP.NET Routingが言及されている場所では、この制限についてのぞき見を聞いたことはありません。 ASP.NET MVCがASP.NETルーティングを使用するという事実は、この影響をさらに大きくします。

どう思いますか?

65
Martin Suchanek

Mvc2と.Net Framework 4.0を使用してこの問題を解決するために、web.configで次を使用することになりました

<httpRuntime maxUrlLength="1000" relaxedUrlToFileSystemMapping="true" />
46
lmingle

Http.sysサービスは、Urlセグメントごとにデフォルトの最大260文字でコーディングされます。

このコンテキストでの「URLセグメント」は、URLの「/」文字の間のコンテンツです。例えば:

http://www.example.com/segment-one/segment-two/segment-three

許可される最大のUrlセグメント長は、レジストリ設定で変更できます。

  • キー:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\HTTP\Parameters
  • 値:UrlSegmentMaxLength
  • タイプ:REG_DWORD
  • データ:(希望する新しいUrlセグメントの最大許容長、たとえば4096)

Http.sys設定の詳細: http://support.Microsoft.com/kb/820129

最大許容値は32766です。これより大きな値を指定すると、無視されます。 (クレジット:Juan Mendes)

この設定の変更を有効にするには、PCの再起動が必要です。 (クレジット:David Rettenbacher、Juan Mendes)

27
David Richoz

これを解決するには、次を実行します。

プロジェクトのルートweb.configのsystem.webノードの下:

<system.web>
    <httpRuntime maxUrlLength="10999" maxQueryStringLength="2097151" />
...

さらに、system.webServerノードの下にこれを追加するか、長いクエリ文字列のセキュリティエラーが発生しました。

<system.webServer>
    <security>
      <requestFiltering>
        <requestLimits maxUrl="10999" maxQueryString="2097151" />
      </requestFiltering>
    </security>
...
27
theJerm

わかりましたので、これを投稿した理由の一部は、回避策を見つけたためでもありました。

これが将来誰かに役立つことを願っています:D

回避策

回避策は非常に単純であり、非常に優れています。

サイトのどの部分が動的パラメーターを使用する必要があるかがわかっているため(動的なパスと長さがあるため)、ASP.NETに到達する前にインターセプトすることで、この長いURLをASP.NETルーティングに送信することを回避できます

IIS7 Url Rewriting(または同等の書き換えモジュール)を入力します。

次のようなルールを設定します。

_    <rewrite>
        <rules>
            <rule>
                <rule name="Remove Category Request Parameters From Url">
                <match url="^category/(\d+)/{0,1}(.*)$" />
                <action type="Rewrite" url="category/{R:1}" />
            </rule>
        </rules>
    </rewrite>
_

基本的に、私たちがしていることは、ダウンストリームの正しいルートを呼び出すことができるのに十分なパスを維持することです。ハッキングするURLパスの残りの部分。

URLの残りはどこに行きますか?

書き換えルールが実行されると、IIS7 URL書き換えモジュールはリクエストにこのヘッダーを自動的に設定します。

_HTTP_X_ORIGINAL_URL
_

下流では、パスを調べる代わりに、動的パスを解析するアプリの一部で:

_HttpContext.Request.Url.PathAndQuery
_

代わりにそのヘッダーを確認します。

_HttpContext.Request.ServerVariables["HTTP_X_ORIGINAL_URL"]
_

問題は解決しました...ほとんど!

スナッグス

ヘッダーへのアクセス

知っておく必要がある場合、IIS7 Rewrite Moduleヘッダーにアクセスするには、次の2つの方法でアクセスできます。

_HttpContext.Request.ServerVariables["HTTP_X_ORIGINAL_URL"]
_

または

_HttpContext.Request.Headers["X-ORIGINAL-URL"]
_

相対パスの修正

また、上記の設定では、すべての相対パス(「〜」で定義されたURL)が壊れていることに気付くでしょう。

これには、ASP.NET MVC HtmlHelperおよびUrlHelperメソッド(Url.Route("Bla")など)で定義されたURLが含まれます。

ASP.NET MVCコードへのアクセスが素晴らしい場所です。

System.Web.Mvc.PathHelper.GenerateClientUrlInternal()メソッドでは、同じURL Rewriteモジュールヘッダーが存在するかどうかを確認するチェックが行われます(上記を参照)。

_// we only want to manipulate the path if URL rewriting is active, else we risk breaking the generated URL
NameValueCollection serverVars = httpContext.Request.ServerVariables;
bool urlRewriterIsEnabled = (serverVars != null && serverVars[_urlRewriterServerVar] != null);
if (!urlRewriterIsEnabled) {
    return contentPath;
}
_

存在する場合は、元のURLを保持するためにいくつかの作業が行われます。

私たちの場合、「通常の」方法でURL書き換えを使用していないため、このプロセスを省略したいと考えています。

元のURLのコンテキストで相対パスを考慮する必要がないため、URLの書き換えが行われていないように見せたいと考えています。

私が考えることができる最も簡単なハックは、そのサーバー変数を完全に削除することでした。したがって、ASP.NET MVCはそれを見つけられませんでした。

_protected void Application_BeginRequest()
{
    string iis7UrlRewriteServerVariable = "HTTP_X_ORIGINAL_URL";

    string headerValue = Request.ServerVariables[iis7UrlRewriteServerVariable];

    if (String.IsNullOrEmpty(headerValue) == false)
    {
        Request.ServerVariables.Remove(iis7UrlRewriteServerVariable);

        Context.Items.Add(iis7UrlRewriteServerVariable, headerValue);
    }
}
_

(上記の方法では、_Request.ServerVariables_からヘッダーを削除していますが、_Context.Items_に隠しておくことに注意してください。この理由は、後でヘッダー値にアクセスする必要があるためです。リクエストパイプ内)

お役に立てれば!

16
Martin Suchanek

GETを使いにくいと思っています。リクエストメソッドをPOSTに変更して、これらのクエリ文字列パラメーターをリクエスト本文に入れてみてください。

長いURLはSEOにも役立ちませんか?

2
Adrian Godong

ハードコードされた最大URL長は 。NET 4.0で修正済み になっているようです。特に、現在web.configセクション:

<httpRuntime maxRequestPathLength="260" maxQueryStringLength="2048" /> 

これにより、許可されるURLの範囲を拡大できます。

1

ASP.NET Web API 4を使用して同様の最大URL長の問題が発生していましたが、わずかに異なるエラーが生成されました:

404エラー

私のための修正は、上記のWeb.configを以下のタグの両方で更新することで説明されました。

<system.web>
    <httpRuntime maxUrlLength="10999" maxQueryStringLength="2097151" />

そして

<system.webServer>
    <security>
      <requestFiltering>
        <requestLimits maxUrl="10999" maxQueryString="2097151" />
      </requestFiltering>
    </security>
1
J. Ventry