Demande get / post simple bloquée en python 3 mais pas en python 2

19

Je travaille sur un simple grattoir Web en python 3 mais quand j'envoie une demande get ou post, la réponse est 403. En python 2, ça marche bien. J'utilise la même version des bibliothèques de requêtes dans les deux versions. J'ai également essayé avec Verify=False/Truemais la différence dans les deux versions demeure.

demandes = 2.22.0

certifi = 2019.9.11

from requests import get
url = 'https://www.gamestop.com/'
header = {
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
    'Accept-Encoding': 'gzip, deflate, br',
    'Accept-Language': 'en-US,en;q=0.5',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:56.0) Gecko/20100101 Firefox/56.0',
    'DNT': '1',
    'Upgrade-Insecure-Requests': '1',
    'Connection': 'keep-alive',
    'Host': 'www.gamestop.com'
}
res = get(url, headers=header, verify=False).status_code
print(res)
# 403 when using python 3.7.4
# 200 when using python 2.7.16

Modifier par @blhsing:

La liste ci-dessous permet de savoir quelles versions spécifiques de Python fonctionnent et quelles versions échouent en fonction des commentaires. Jusqu'à présent, les succès et les échecs ont été cohérents pour chaque version Python spécifique sur toutes les plateformes.

N'hésitez pas à modifier cette section de la question avec vos propres résultats ainsi que les versions spécifiques de Python utilisées pour produire les résultats.

2.7.14 works (blhsing)
2.7.16 works (repl.it)
3.6.5 works (blhsing)
3.6.8 fails (Reinderien and blhsing)
3.7.3 works (wim and blhsing)
3.7.4 fails (repl.it and blhsing)
3.8.0 fails (OP)

Démo sur repl.it: Python 2.7.16 et Python 3.7.4

EDM
la source
Il convient de noter que cela fonctionne en Python 3.6 mais pas en 3.7.
blhsing
J'obtiens "Accès refusé" même dans Firefox - après quelques exécutions de code en Python 3.7. Je n'ai pas essayé dans Firefox avant d'exécuter Python - peut-être que je suis bloqué après avoir utilisé du code Python ou peut-être qu'il bloque pour une autre raison - mauvaise adresse IP, mauvais pays, problème sur le serveur.
furas
1
@blhsing yep c'est bizarre, je suppose que j'irai avec 3.6 alors, merci pour la note
EDM
2
C'est étrange. Utilisez Wireshark et comparez les requêtes envoyées par Python 3.6 et 3.7. Il doit y avoir une différence que le serveur détecte.
GordonAitchJay
1
Cela est probablement dû à différents openssl ( ssl.OPENSSL_VERSION). Vous n'avez pas besoin de tous ces en-têtes à reproduire, juste une simple vieille get (url) le fera.
wim

Réponses:

9

C'est l'exception levée par urlib3:

/home/runner/.local/share/virtualenvs/python3/lib/python3.7/site-packages/urllib3/connectionpool.py:1004: InsecureRequestWarning: une demande HTTPS non vérifiée est en cours. L'ajout d'une vérification de certificat est fortement conseillé. Voir: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning,

Selon les dernières notes de version, section 1.25.5 (2019-09-19) :

Ajoutez une atténuation pour BPO-37428 affectant Python <3.7.4 et OpenSSL 1.1.1+ qui a entraîné l'activation de la vérification des certificats lors de l'utilisation de cert_reqs = CERT_NONE. (Numéro 1682 )

Vous pouvez suivre le problème sur Github , il a été fermé.

TLDR

L'utilisateur @sethmlarson sur Github a trouvé ce bug sur urllib3 :

create_urllib3_context ():

    # Enable post-handshake authentication for TLS 1.3, see GH #1634. PHA is
    # necessary for conditional client cert authentication with TLS 1.3.
    # The attribute is None for OpenSSL <= 1.1.0 or does not exist in older
    # versions of Python.
    if getattr(context, "post_handshake_auth", None) is not None:
        context.post_handshake_auth = True

la définition de cette valeur sur Truepermettra la vérification des certificats de serveur, au lieu d'être désactivée.

Naor Tedgi
la source