2012-02-01 16 views
14

Zwykle nie wpisałbym tego tytułu w pytaniu, ale jestem pewien, że to błąd (lub projekt?)Możliwy błąd z routingiem ASP.NET MVC 3?

Stworzyłem zupełnie nową aplikację sieci Web ASP.NET MVC 3.

Potem poszedłem na stronę/Strona główna/Informacje.

URL na tej stronie:

http://localhost:51419/Home/About

Potem zmienił adres URL do tego:

http://localhost:51419/(A(a))/Home/About

a strona działa? Patrząc na wartości trasy, kontroler = Strona główna, Działanie = Informacje. Zignorowano pierwszą część?

A jeśli spojrzeć na wszystkie linki w źródle:

<link href="/(A(a))/Content/Site.css" rel="stylesheet" type="text/css" /> 
<script src="/(A(a))/Scripts/jquery-1.5.1.min.js" type="text/javascript"></script> 
<script src="/(A(a))/Scripts/modernizr-1.7.min.js" type="text/javascript"></script> 

<li><a href="/(A(a))/">Home</a></li> 
<li><a href="/(A(a))/Home/About">About</a></li> 

Zobacz, jak to utrzymywał, że pierwszej części? To tak, jak silnik routingu myśli, że jest częścią domeny czy coś takiego?

Mam wrażenie, że to regex sprawa, bo jeśli zmienię adres URL:

http://localhost:51419/(a(a))/Home/About

(np zmienił wielkiej litery A na małe litery)

To 404 jest.

Czy ktoś może rzucić trochę światła na to? Czy to błąd, czy projekt?

+2

To rzadka sprawa, że ​​wpis z "możliwym błędem" w tytule jest godny szacunku, IMO. Ten jest. –

+1

@AndrewBarber - wiem. :) To czysty fuks, natknąłem się na ten. Google indeksowało niektóre dziwne adresy URL za pomocą przewodników, spowodowanych przez błąd w naszej aplikacji. – RPM1984

Odpowiedz

5

Wygląda na to, że ma on związek z sesjami bez plików cookie w potoku ASP.NET. To pasków, które URL wzór wewnątrz CookielessHelper.cs (System.Web.Security) podczas przetwarzania żądania:

// This function is called for all requests -- it must be performant. 
    // In the common case (i.e. value not present in the URI, it must not 
    // look at the headers collection 
    internal void RemoveCookielessValuesFromPath() 
    { 
     // See if the path contains "/(XXXXX)/" 
     string path  = _Context.Request.ClientFilePath.VirtualPathString; 
     // Optimize for the common case where there is no cookie 
     if (path.IndexOf('(') == -1) { 
      return; 
     } 
     int  endPos = path.LastIndexOf(")/", StringComparison.Ordinal); 
     int  startPos = (endPos > 2 ? path.LastIndexOf("/(", endPos - 1, endPos, StringComparison.Ordinal) : -1); 

     if (startPos < 0) // pattern not found: common case, exit immediately 
      return; 

     if (_Headers == null) // Header should always be processed first 
      GetCookielessValuesFromHeader(); 

     // if the path contains a cookie, remove it 
     if (IsValidHeader(path, startPos + 2, endPos)) 
     { 
      // only set _Headers if not already set 
      if (_Headers == null) { 
       _Headers = path.Substring(startPos + 2, endPos - startPos - 2); 
      } 
      // Rewrite the path 
      path = path.Substring(0, startPos) + path.Substring(endPos+1); 

      // remove cookie from ClientFilePath 
      _Context.Request.ClientFilePath = VirtualPath.CreateAbsolute(path); 
      // get and append query string to path if it exists 
      string rawUrl = _Context.Request.RawUrl; 
      int qsIndex = rawUrl.IndexOf('?'); 
      if (qsIndex > -1) { 
       path = path + rawUrl.Substring(qsIndex); 
      } 
      // remove cookie from RawUrl 
      _Context.Request.RawUrl = path; 

      if (!String.IsNullOrEmpty(_Headers)) { 
       _Context.Request.ValidateCookielessHeaderIfRequiredByConfig(_Headers); // ensure that the path doesn't contain invalid chars 
       _Context.Response.SetAppPathModifier("(" + _Headers + ")"); 

       // For Cassini and scenarios where aspnet_filter.dll is not used, 
       // HttpRequest.FilePath also needs to have the cookie removed. 
       string filePath = _Context.Request.FilePath; 
       string newFilePath = _Context.Response.RemoveAppPathModifier(filePath); 
       if (!Object.ReferenceEquals(filePath, newFilePath)) { 
        _Context.RewritePath(VirtualPath.CreateAbsolute(newFilePath), 
             _Context.Request.PathInfoObject, 
             null /*newQueryString*/, 
             false /*setClientFilePath*/); 
       } 
      } 
     } 
    } 

Twój wzór pasuje to:

/////////////////////////////////////////////////////////////////////// 
    /////////////////////////////////////////////////////////////////////// 
    // Make sure sub-string if of the pattern: A(XXXX)N(XXXXX)P(XXXXX) and so on. 
    static private bool IsValidHeader(string path, int startPos, int endPos) 
    { 
     if (endPos - startPos < 3) // Minimum len is "X()" 
      return false; 

     while (startPos <= endPos - 3) { // Each iteration deals with one "A(XXXX)" pattern 

      if (path[startPos] < 'A' || path[startPos] > 'Z') // Make sure pattern starts with a capital letter 
       return false; 

      if (path[startPos + 1] != '(') // Make sure next char is '(' 
       return false; 

      startPos += 2; 
      bool found = false; 
      for (; startPos < endPos; startPos++) { // Find the ending ')' 

       if (path[startPos] == ')') { // found it! 
        startPos++; // Set position for the next pattern 
        found = true; 
        break; // Break out of this for-loop. 
       } 

       if (path[startPos] == '/') { // Can't contain path separaters 
        return false; 
       } 
      } 
      if (!found) { 
       return false; // Ending ')' not found! 
      } 
     } 

     if (startPos < endPos) // All chars consumed? 
      return false; 

     return true; 
    } 
+0

Hmm, sooo ... to jest błąd? Nie jestem pewien, czy jest to rdzeń ASP.NET, ponieważ ten kod ma sens. ALE, silnik routingu ASP.NET (cóż, przynajmniej routing MVC), IMO nie powinien akceptować tego jako części trasy (np. Nie powinien się zgadzać). Czy powinienem to podnieść ze stwardnieniem rozsianym? – RPM1984

+0

@ RPM1984 Nie, jest to wyraźnie "z założenia", jak śledzą, który użytkownik jest zalogowany, gdy pliki cookie nie są dostępne. Po prostu udawaj, że nigdy tego nie zauważyłeś i wszystko będzie dobrze. –

+0

@RobertLevy - nie mogę tego zignorować. Tak naprawdę dzieje się to z aplikacją na żywo. Jak już wspomniałem w komentarzu, Google indeksuje niektóre dziwne adresy URL, które pasują do tego wzorca. Ponieważ MVC akceptuje je jako ważne trasy, po prostu dociera do moich kontrolerów, a następnie umiera. Kiedy naprawdę powinni być 404'ed od początku. Adresy URL są również losowe, więc nie mogę łatwo wprowadzić przepisywania w miejscu. Wystarczająco fair jest to "z założenia" dla ASP.NET, ale myślę, że jest to błąd w MVC. NIE powinien akceptować tego jako trasy. – RPM1984

-1

zgadzam się z analizą @pjumble, ale nie do jego rozwiązanie.
Wyłącz uwierzytelnianie bez dostępu do pliku dla uwierzytelniania formularza lub anonimowego uwierzytelniania.

Uniemożliwi to użytkownikom wyłączanie plików cookie w celu uwierzytelnienia. Ale kogo to obchodzi, teraz wszyscy mają ciasteczka aktywowane, ponieważ żadna nowoczesna strona internetowa nie będzie działać.

Dodaj w pliku web.config:

<anonymousIdentification enabled="false" /> 
<authentication mode="None" /> 

lub

<anonymousIdentification enabled="true" cookieless="UseCookies" ... /> 
<authentication mode="Forms"> 
    <forms name="Auth" cookieless="UseCookies" ... /> 
</authentication> 
+0

BTW, co było "rozwiązaniem" @ pjumble, nie widzę jednego, tylko diagnoza. – RPM1984

+0

zablokowałbyś pewną liczbę użytkowników, którzy mogliby się zalogować, tylko z powodu głupiego, pozbawionego znaczenia dziwactwa w analizie adresów URL w .net? –

+0

"Ale kogo to obchodzi" większość działu sprzedaży na początek ... – Basic

0

Można spróbować dodawania IgnoreRoute do wyznaczaniu trasy - ale muszę przyznać, że nie jestem pewien, jaki format, aby zapewnić aby dopasować wszystkie możliwe ścieżki do gotowania.

Powiązane problemy