web-dev-qa-db-fra.com

Pourquoi "Content-Length: 0" in POST demandes?

Un client envoie parfois POST des demandes avec Content-Length: 0 lors de la soumission d'un formulaire (10 à plus de 40 champs).

Nous l'avons testé avec différents navigateurs et à différents endroits, mais nous n'avons pas pu reproduire l'erreur. Le client utilise Internet Explorer 7 et un proxy.

Nous leur avons demandé de laisser leur administrateur système voir le problème de leur côté. Exécuter des tests sans proxy, etc.

En attendant (six mois plus tard et toujours pas de réponse), je suis curieux de savoir si quelqu'un d'autre connaît des problèmes similaires avec une demande Content-Length: 0. Peut-être de l'intérieur d'un réseau Windows avec un proxy spécial pour les grandes entreprises.

Existe-t-il un problème connu avec Internet Explorer 7? Avec un système de proxy? Le réseau Windows lui-même?

Google n'a montré que quelque chose dans le contexte de l'authentification NTLM (et telle), mais nous ne l'utilisons pas dans l'application Web. Peut-être que c'est dans la manière dont le proxy fonctionne dans le réseau du client avec des identifiants Windows? (Je ne suis pas un expert Windows. Juste deviner.)

Je n'ai pas d'autres informations sur l'infrastructure.

MISE À JOUR: En décembre 2010, il était possible d'informer un administrateur à ce sujet, incl. liens à partir des réponses ici. Le contact était dû à un autre problème causé par le proxy également. Aucun retour depuis. Et les messages d'erreur sont toujours là. Je ris pour m'empêcher de pleurer.

MISE À JOUR 2: Ce problème existe depuis le milieu de 2008. Tous les quelques mois, le client est énervé et souhaite que le problème soit résolu dès que possible. Nous leur envoyons à nouveau tous les anciens e-mails et leur demandons de contacter leurs administrateurs pour résoudre le problème ou effectuer d'autres tests. En décembre 2010, nous avons pu envoyer certaines informations à un administrateur. Pas de retour d'information. Le problème n'est pas résolu et nous ne savons pas s'ils ont même essayé. Et en mai 2011, le client écrit à nouveau et souhaite que cela soit corrigé. La même personne qui a toutes les informations depuis 2008.

Merci pour toutes les réponses. Vous avez aidé beaucoup de gens, comme je peux le voir d'après certains commentaires. Dommage que le monde réel soit aussi grotesque pour moi.

UPDATE 3: mai 2012 et je me demandais pourquoi nous n'avions pas reçu d'autre demande pour résoudre ce problème (voir UPDATE 2). A examiné le protocole d'erreur, qui ne signale cette erreur que chaque fois que cela se produit (environ 15 par jour). Cela s'est arrêté fin janvier 2012. Personne n'a rien dit. Ils doivent avoir fait quelque chose avec leur réseau. Tout va bien maintenant. De l'été 2008 à janvier 2012. Dommage, je ne peux pas vous dire ce qu'ils ont fait.

MISE À JOUR 4: septembre 2015. Le site Web devait collecter des données et les transmettre au site Web principal du client. Il y avait une API avec un compte. Chaque fois qu'il y avait un problème, ils nous contactaient, même si le problème était clairement de l'autre côté. Depuis quelques semaines, nous ne pouvons pas leur envoyer les données. Le compte n'est plus disponible. Ils ont eu une relance et je ne trouve plus les pages qui ont utilisé les données de notre site. Le rapport de bug n'est pas répondu et personne ne se plaint. Je suppose qu'ils viennent juste de terminer ce projet.

MISE À JOUR 5: mars 2017. L'API a cessé de fonctionner à l'été 2015. Le client semble continuer à payer pour le site et l'utilise toujours en février 2017. J'imagine qu'il l'utilise comme archive. Ils ne créent ni ne mettent à jour aucune donnée. Ce bogue ne réapparaîtra probablement pas après le mystérieux correctif de janvier 2012. Mais ce serait le problème de quelqu'un d'autre. Je pars.

50
stesch

Internet Explorer n'envoie pas les champs de formulaire s'ils sont publiés à partir d'un site authentifié (NTLM) sur un site non authentifié (anonyme). 

Il s'agit d'une fonctionnalité pour les situations de réponse à des menaces (sites Web sécurisés par NTLM ou Kerberos) où IE peut s'attendre à ce que la première demande POST conduise immédiatement à une réponse HTTP 401 Authentification requise(qui inclut un défi), et seule la deuxième demande POST (qui inclut la réponse au défi) sera réellement acceptée. Dans ces situations, IE ne télécharge pas le corps de requête éventuellement volumineux avec la première requête pour des raisons de performances. Merci à EricLaw pour avoir posté cette information dans les commentaires.

Ce problème se produit chaque fois qu'un HTTP POST est créé à partir d'une page authentifiée par NTLM (c.-à-d. Intranet) vers une page non authentifiée (c.-à-d. Internet), ou si la page non authentifiée fait partie d'un jeu de cadres. la page est authentifiée.

La solution consiste à utiliser une requête GET en tant que méthode de formulaire ou à vous assurer que la page non authentifiée est ouverte dans un nouvel onglet/fenêtre (favori/cible du lien) sans jeu de cadres partiellement authentifié. Dès que le modèle d'authentification de la fenêtre entière est cohérent, IE recommencera à envoyer le contenu du formulaire.


40
Tomalak

Ceci est facile à reproduire avec MS-IE et un filtre d'authentification NTLM côté serveur. J'ai le même problème avec JCIFS (1.2 .), struts 1. et MS-IE 6/7 sur XP-SP2. Il a finalement été corrigé. Il existe plusieurs solutions pour le résoudre. 

  1. changez la méthode de formulaire de POST (paramètre par défaut de struts) en GET. Pour la plupart des pages avec des formulaires de petite taille, cela fonctionne bien. Malheureusement, j'ai éventuellement plus de 50 enregistrements à envoyer en flux HTTP vers le serveur. IE a une limite d'URL GET de 2038 octets (pas la longueur du paramètre, mais la longueur totale de l'URL). Il s’agit donc d’une solution rapide, mais qui ne m’applique pas.

  2. envoyer un GET avant POST action en cours d'exécution. Cela a été recommandé dans MS-KB. Mon projet a de nombreuses procédures héritées et je ne prendrais pas le risque au bon moment. Je n'ai jamais essayé cette solution car elle nécessite encore un traitement d'authentification supplémentaire lorsque GET est reçu par la couche de filtre en fonction de ma compréhension de MS-KB et je ne souhaite pas modifier le comportement avec les autres navigateurs, par exemple. Firefox, Opera.

  3. détecter si POST a été envoyé avec une longueur de contenu nulle (vous pouvez l'obtenir à partir de la structure de hachage des propriétés d'en-tête avec votre structure). Si c'est le cas, déclenchez un cycle d'authentification NTLM en obtenant le code d'interrogation de DC ou cache et attend une réponse NTLM. Lorsque le message NTLM type2 est reçu et que la session est toujours valide, vous n'avez pas vraiment besoin d'authentifier l'utilisateur, mais transmettez-le simplement à l'action attendue si POST content-length n'est pas nul. BTW, cela augmenterait les trafics du réseau. Vérifiez donc le paramètre de durée de vie du cache et SMB la configuration de la session soTimeOut avant d'appliquer la modification plz . Ou, plus simplement, vous pouvez simplement envoyer un statut non autorisé à 401 à MS-IE et le navigateur doit envoyer back POST demande avec données en réponse.

  4. MS-KB a fourni un correctif logiciel avec KB-923155 (je ne pouvais pas publier plus d'un lien en raison d'un numéro de réputation faible: {), mais il semble ne pas fonctionner. Est-ce que quelqu'un pourrait publier un correctif pratique ici? Merci :) Voici un lien pour référence, http://www.websina.com/bugzero/kb/browser-ie.html

14
maxwu

Nous avons un client sur notre système avec exactement le même problème. Nous l'avons identifié en direction du proxy/pare-feu. IAS de Microsoft. Cela enlève le corps de POST et envoie content-length: 0. Nous ne pouvons pas beaucoup en contourner le problème et nous voulons utiliser les requêtes GET car cela expose les noms d'utilisateur/mots de passe, etc. Il y a près de 7 000 utilisateurs sur notre système et un seul avec le problème ... et un seul utilisant Microsoft IAS, il doit donc en être ainsi.

6
Scott

Il y a de bonnes chances que le problème soit que le serveur proxy implémente HTTP 1.0.

Dans HTTP 1.0, vous devez utiliser le champ d’en-tête Content-Length: ( Voir la section 10.4 ici )

Un Content-Length valide est requis sur toutes les requêtes HTTP/1.0 POST. Un Le serveur HTTP/1.0 devrait répondre avec un 400 (mauvaise demande) message s'il ne le peut pas déterminer la longueur de la demande le contenu du message.

La demande entrant dans le proxy est HTTP 1.1 et n'a donc pas besoin d'utiliser le champ d'en-tête Content-Length. L'en-tête Content-Length est généralement utilisé mais pas toujours. Voir l'extrait suivant de la HTTP 1.1 RFC S. 14.13

Les applications DEVRAIENT utiliser ce champ pour indiquez la longueur de transfert du fichier corps du message, à moins que ce ne soit interdit par les règles dans section 4.4 . Toute longueur de contenu supérieure à ou égal à zéro est une valeur valide.

La section 4.4 décrit comment déterminer la longueur d'un corps de message si a Content-Length n'est pas donné.

Ainsi, le serveur proxy ne voit pas l'en-tête Content-Length, ce qui est supposé être absolument nécessaire dans HTTP 1.0 s'il existe un corps. Donc, on suppose 0 pour que la demande atteigne finalement le serveur. N'oubliez pas que le proxy ne connaît pas les règles de la spécification HTTP 1.1, il ne sait donc pas comment gérer la situation lorsqu'il n'y a pas d'en-tête Content-Length. 

Êtes-vous sûr à 100% que votre demande spécifie l'en-tête Content-Length? S'il utilise un autre moyen tel que défini dans la section 4.4, car il pense que le serveur correspond à la version 1.1 (car il ne connaît pas le proxy 1.0 entre les deux), vous aurez alors le problème décrit. 

Vous pouvez peut-être utiliser HTTP GET à la place pour contourner le problème. 

4
Brian R. Bondy

Il s’agit d’un problème connu pour Internet Explorer 6, mais pas pour les 7 que je connais. Vous pouvez installer ce correctif pour le correctif IE6 KB831167 .

Vous pouvez en savoir plus à ce sujet ici

Quelques questions pour vous:

  • Savez-vous quel type de proxy?
  • Savez-vous s'il y a un corps réel envoyé dans la demande?
  • Cela se produit-il systématiquement à chaque fois? Ou seulement parfois?
  • Y a-t-il des données binaires envoyées dans la demande? Peut-être que les données commencent par un\0 et que le proxy a un bogue avec des données binaires. 
3
Brian R. Bondy

Si l'utilisateur utilise un proxy ISA qui utilise l'authentification NTLM, le problème est semblable à celui auquel une solution est fournie (un correctif du proxy ISA)

http://support.Microsoft.com/kb/942638
Les demandes POST n'ayant pas de corps POST peuvent être envoyées à un serveur Web publié dans ISA Server 2006

2
GStephens

Êtes-vous sûr que ces demandes proviennent d'un "client"?

J'ai déjà eu ce problème avec des bots auparavant; ils interrogent parfois les sites pour les formulaires "nous contacter" en envoyant des requêtes POST vides en fonction de l'URI de l'action dans les balises FORM qu'ils découvrent lors de l'exploration.

1
JasonTrue

La présence et les valeurs possibles de l'en-tête ContentLength dans HTTP sont décrites dans la RFC HTTP (je suppose 1/1):

http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.13

En HTTP, il DEVRAIT être envoyé chaque fois que la longueur du message peut être déterminée avant d'être transférée

Voir également:

Si un message est reçu avec les deux un Champ d'en-tête Transfer-Encoding et un champ d'en-tête Content-Length, ce dernier DOIT être ignoré.http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.4

Peut-être que votre message contient un en-tête Transfer-Encoding?

Édition ultérieure: veuillez également noter que "DEVRAIT" tel qu’il est utilisé dans la RFC est très important et n’équivaut pas à "DOIT":

3. DEVRAIS-JE Ce mot, ou l’adjectif "RECOMMANDÉ", signifie qu’il existe peut exister des raisons valables dans des circonstances particulières pour ignorer un point particulier, mais toutes les implications doivent être comprises et soigneusement pesé avant de choisir un cours différent. Réf: http://www.ietf.org/rfc/rfc2119.txt

1
diciu

curl envoie des demandes PUT/POST avec Content-Length: 0 lorsqu'il est configuré pour utiliser un proxy HTTP. C'est une astuce pour surmonter la mise en mémoire tampon requise dans le cas d'une première demande PUT/POST non autorisée au proxy. Dans le cas de GET/HEAD requêtes curl répète simplement la requête. Le schéma pour PUT/POST est comme:

  1. Envoyez la première demande PUT/POST avec Content-Length défini sur 0.

  2. Obtenez une réponse. Le code de statut HTTP de 407 signifie que nous devons utiliser une autorisation proxy Préparez les en-têtes pour l'authentification proxy pour la demande d'envoi.

  3. Envoyez à nouveau la demande avec les en-têtes renseignés pour l'authentification proxy et les données réelles vers POST/PUT.

0
user1641854

Un de nos clients utilisait le même site Web en mode anonyme et NTLM (sur des ports différents). Nous avons découvert que dans notre cas, la version 401 était liée à l'application Riverbed Steelhead utilisée pour l'optimisation http. Le premier signal nous indiquant cette direction était un en-tête X-RBT-Optimized-By. Le problème était la fonctionnalité Gratuitous 401:

Cette fonctionnalité peut être utilisée à la fois par demande et par connexion L’authentification, mais c’est plus efficace quand elle est utilisée avec une requête authentification. Avec l'authentification par demande, chaque demande doit être authentifié sur le serveur avant que le serveur serve le objet au client. Cependant, la plupart des navigateurs ne mettent pas en cache le fichier .__ du serveur. réponse nécessitant une authentification et par conséquent, il en perdra un. Aller-retour pour chaque demande GET. Avec Gratuitous 401, le côté client L’appliance Steelhead mettra en cache la réponse du serveur et le client envoie la requête GET sans en-tête d'authentification, ce sera Répondez localement avec un message «401 non autorisé» et enregistrez ainsi un aller-retour. Notez que le module HTTP ne participe pas au authentification proprement dite. Ce que le module HTTP fait, c'est informer le client pour lequel le serveur nécessite une authentification sans nécessiter perdre un aller-retour.

0
wdk

J'ai également eu un problème où les demandes du navigateur IE 11 d'un client avaient Content-Length: 0 et n'incluaient pas le contenu attendu POST. Lorsque le client utilisait Firefox ou Chrome, le contenu attendu était inclus dans la demande.

J'ai résolu le problème car le client utilisait une URL HTTP au lieu d'une URL HTTPS (par exemple, http://..., pas https://...) et notre application utilise le système HSTS. Il semble qu'il y ait un problème dans IE 11 qui, lorsqu'une demande est mise à niveau vers HTTPS en raison de HSTS, perd le contenu de la demande.

Amener le client à corriger l'URL à https://... a abouti à l'inclusion du contenu dans la demande POST et à la résolution du problème.

Je n’ai pas cherché à savoir s’il s’agissait bien d’un bogue dans IE 11 à ce stade.

0
matthewrwilton

Le correctif de Microsoft pour KB821814 peut définir Content-Length sur 0:

Le correctif décrit dans cet article implémente une modification de code dans Wininet.dll pour:

  • Détecte la condition RESET sur une demande POST.
  • Enregistrez les données à publier.
  • Réessayez la demande POST avec la longueur de contenu définie sur 0. Cela empêche la réinitialisation et permet au processus d'authentification de se terminer.
  • Réessayez la demande d'origine POST.
0
user151236

Google indique également cela sous la forme d'un bogue IE (certaines versions, en tout cas) après qu'une connexion https ait atteint le délai de conservation et se reconnecte au serveur. La solution semble être de configurer le serveur pour qu'il n'utilise pas keepalive pour IE sous https.

0
ysth