2013-02-27 1 views
17

IISおよびASP.NET(MVC)has some glitchesパス(%query-stringではない、クエリ文字列は問題ありません)で%-encodingを指定してURLを処理する場合。どうすればこの問題を回避できますか?つまり、リクエストされた実際のURLはどのように入手できますか?例えばパスにパーセントでエンコードされた部分がある場合でも、実際のURLを確実に取得するにはどうすればよいですか?

、Iは/x?a=b/x%3Fa%3Db及び(別々に)に移動した場合 - これらの両方が.Request.Url/x?a=bとしての報告 - パスでエンコードされたデータが誤って報告されているからです。

+0

考えている間、StackOverflowはスニペットサイトではなく、あなたが特定するもの、つまりブログを投稿する場所ではありません。質問と回答のタイムスタンプは、あなたがここに来て両方を投稿できる状態になったことを示しています。本当に助けが必要な質問のみ投稿してください。コミュニティーと情報を共有するより適切な方法があります。 –

+29

@Chris [自己回答は常に受け入れられています](http://blog.stackoverflow.com/2011/07/its-ok-to-ask-and-answer-your-own-questions/)。尋ねる*の一部として*答えることを可能にする決定はまた非常に故意に取られた - そのコードは非常に意図的に加えられた。私は知っている:私はそのチームで働いています。さらに、このコードは、[この問題によって引き起こされるスタックオーバーフローのバグ](http://meta.stackexchange.com/q/169356)を修正した後で、ユーザーが「メタ」について要求する要求の一部として共有されています。 Dr:あなた自身の質問に答えることは、質疑応答が適切に形成され、適切である限り、明示的にOKです。 –

答えて

21

これを解決する方法は、基本となるサーバー変数を調べることです。 URL変数には、がデコードされた値が含まれています。 QUERY_STRING変数には、まだエンコードされたクエリが含まれています。 のエンコードは、URLの部分には、/などのオリジナルの形式が含まれているため、この部分を元に戻すことはできません。盲目的にエンコードすれば、不要な%2f値が得られます。しかし、問題のあるケースを見つけることができます:

private static readonly Regex simpleUrlPath = new Regex("^[-a-zA-Z0-9_/]*$", RegexOptions.Compiled); 
private static readonly char[] segmentsSplitChars = { '/' }; 
// ^^^ avoids lots of gen-0 arrays being created when calling .Split 
public static Uri GetRealUrl(this HttpRequest request) 
{ 
    if (request == null) throw new ArgumentNullException("request"); 
    var baseUri = request.Url; // use this primarily to avoid needing to process the protocol/authority 
    try 
    { 
     var vars = request.ServerVariables; 
     var url = vars["URL"]; 
     if (string.IsNullOrEmpty(url) || simpleUrlPath.IsMatch(url)) return baseUri; // nothing to do - looks simple enough even for IIS 

     var query = vars["QUERY_STRING"]; 
     // here's the thing: url contains *decoded* values; query contains *encoded* values 

     // loop over the segments, encoding each separately 
     var sb = new StringBuilder(url.Length * 2); // allow double to be pessimistic; we already expect trouble 
     var segments = url.Split(segmentsSplitChars); 
     foreach (var segment in segments) 
     { 
      if (segment.Length == 0) 
      { 
       if(sb.Length != 0) sb.Append('/'); 
      } 
      else if (simpleUrlPath.IsMatch(segment)) 
      { 
       sb.Append('/').Append(segment); 
      } 
      else 
      { 
       sb.Append('/').Append(HttpUtility.UrlEncode(segment)); 
      } 
     } 
     if (!string.IsNullOrEmpty(query)) sb.Append('?').Append(query); // query is fine; nothing needing 
     return new Uri(baseUri, sb.ToString()); 
    } 
    catch (Exception ex) 
    { // if something unexpected happens, default to the broken ASP.NET handling 
     GlobalApplication.LogException(ex); 
     return baseUri; 
    } 
} 
+2

私はこのコード、Marc +1が大好きです。 – Brian

関連する問題