2012-12-04 16 views
8

Mam aplikację PHP (PHP 5.3.2) działającą na serwerze Apache (2.2.14) na serwerze Linux. Więcej niż raz w swojej historii użytkownik zobaczył w swoich przeglądarkach następujący komunikat: "Żądaj zbyt dużej jednostki". Pierwsze wyszukiwanie w Google sugerowało, że dzieje się tak, gdy przesłany plik jest za duży lub gdy ciasteczka są za duże. Ale nie dzieje się to podczas przesyłania plików, tylko przy logowaniu i zawsze na stronie logowania. Użytkownik wprowadza tę stronę za pomocą zwykłego formularza POST na stronie. Pliki cookie zawierają tylko identyfikator sesji.Apache, PHP Niepoprawna długość zawartości

Co więcej, apache rejestruje "Nieprawidłowa długość treści". Jest to rejestrowane przed wykonaniem któregokolwiek z moich kodów. $ _POST jest pusty, mimo że powinien zawierać pewne dane. Kiedy dodaje się następujący wiersz:

error_log("Content-Length: ".$_SERVER['CONTENT_LENGTH']); 

mówi

Content-Length: 32, 32 

, który wydaje się być rzeczywiście nieważne. Zmiana przeglądarki lub resetowanie komputera użytkownika wydaje się nie pomagać. Wszystko zaczęło działać następnego dnia.

Gdzie może leżeć problem? Czy jest to coś z Apache, PHP, ustawienia sieciowe użytkownika? Jeśli potrzebuję dodać więcej informacji, daj mi znać.

+1

Może [ta odpowiedź] (http://stackoverflow.com/questions/1361451/get-size-post-request-in-php#3259068) może pomóc. – Wh1T3h4Ck5

+0

Próbowałem niektóre z tych opcji, ale bez wyników. Na przykład strlen (file_get_contents ('php: // input')) to 0. – PWojnar

+1

Spróbuj: 'strlen (file_get_contents ('php: // stdin'))' zamiast – Dale

Odpowiedz

2

Najprostszym sposobem zbadania kwestii jak to jest używać TCPDump do przechwytywania pakietów przesyłanych między klientem a serwerem do pliku, a następnie użyj Wireshark aby pakiety jako strumień TCP.

Przykładem polecenia przechwycenia pakietów byłby.

tcpdump -i eth0 -vvv -A 'hosta 123.123.10.12 & & port 80' -w eth0.dat

Ponieważ jest to strona logowania, prawdopodobnie będzie konieczne do dekodowania strumienia TCP, jak powinno być za HTTPS - co można zrobić za pomocą instrukcji od http://segfault.in/2010/11/decrypt-https-traffic-using-wireshark-and-key-file/

Plasmid87 jest prawie na pewno poprawny - wygląda na to, że jeden z nagłówków po prostu rośnie masowo iw końcu staje się większy niż Apache LimitRequestFieldSize.

Dopóki rośnie wolno, a nie wszystkie naraz, można to sprawdzić, sprawdzając zmienne globalne.

function checkVars(){ 
    $varsToCheck = array($GLOBALS, $_SERVER, $_GET, $_POST, $_FILES, $_REQUEST, $_SESSION, $_ENV, $_COOKIE); 

    foreach($varToCheck as $var){ 
     foreach($var as $key => $value){ 

      if(count($key) > 1024){ 
       logToFile("Found ridiculous key: ".$key." value is ".$value); 
      } 
      if(count($value) > 1024){ 
       logToFile("Found ridiculous value for key: ".$key." value is ".$value); 
      } 
     } 
    } 
} 
5

W minionych dniach napotkaliśmy komunikaty "Niepoprawna długość treści" zarejestrowane przez Apache w error_log. gąsienicowe problem do pewnego gościa od kilku konkretnych klas IP, na przykład Movistar Argentyna: 200.81.44.201 Dalsze sprawdzanie żądanie z tcpdump/whireshark Zaobserwowaliśmy, że żądanie POST zawarty jakiś

duplicate Headers, namely Content-Length and Content-Type

prawdziwym problemem jest z Content-Length, ponieważ Apache leczeniu wielu zmiennych, poprzez ich łączenie, na przykład:

Content-Length: 51 
Content-Length: 51 

rezultatem będzie:

Content-Length: 51, 51 

Następnie Apache próbuje przekonwertować ciąg "51, 51" na liczbę całkowitą, która nie jest możliwa. W nowszym Apache> 2.2.17, lub z przeniesionymi łatami Apache rejestruje błąd: 413 Żądanie jednostki Zbyt duże, ze starszym Apache, proces po prostu pochłania dużo czasu procesora. Za tą klasą IP widzimy bardziej różnych klientów, więc być może są to błędnie skonfigurowane serwery proxy bramy 3G, ponieważ duplikują te nagłówki. więc znaleźć rozwiązanie do konfiguracji Apache przepisać żądań z jednego Content-Length oraz Content-Type jeden Nagłówki: Oto mój kod do tego, używając mod_headers i SetEnvIfNoCase włożony w httpd.conf:

SetEnvIfNoCase Content-Length (.*), MyContentLength=$1 
SetEnvIfNoCase Content-Type (.*), MyContentType=$1 
RequestHeader set Content-Length: "%{MyContentLength}e" env=MyContentLength 
RequestHeader set Content-Type: "%{MyContentType}e" env=MyContentType 

Możesz testować i używać tego kodu, aby odfiltrować zduplikowane zmienne nagłówka HTTP Content-Length.

Powiązane problemy