【问题标题】:How to implement ajax request using Python Request如何使用 Python Request 实现 ajax 请求
【发布时间】:2020-05-05 06:20:05
【问题描述】:

我正在尝试使用 Python 请求登录网站。不幸的是,它在打印其内容时总是显示此错误。

b'<head><title>Not Acceptable!</title></head><body><h1>Not Acceptable!</h1><p>An appropriate representation of the requested resource could not be found on this server. This error was generated by Mod_Security.</p></body></html>

供参考我的代码

from requests import Session
import requests

INDEX_URL = 'https://phpzag.com/demo/ajax_login_script_with_php_jquery/index.php'
URL = 'https://phpzag.com/demo/ajax_login_script_with_php_jquery/welcome.php'
LOGIN_URL = 'https://phpzag.com/demo/ajax_login_script_with_php_jquery/login.php' # Or whatever the login request url is
payload = {'user_email': 'test@phpzag.com','password':'test'}

s = requests.Session()
user_agent = {'User-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.129 Safari/537.36'}
t=s.post(LOGIN_URL, data=payload, headers=user_agent)
r=s.get('https://phpzag.com/demo/ajax_login_script_with_php_jquery/welcome.php',headers=user_agent,cookies=t.cookies.get_dict())
print(r.content)

我可以知道缺少什么以及如何从中获取欢迎页面的 HTML 代码

更新

我正在尝试在登录身份验证后进行 API 调用。但是,我无法成功登录身份验证。因此我无法获得 API 调用的响应。根据我的想法,由于多因素身份验证,它失败了。我需要知道如何实现它?

例如:www.abc.com 是网站的 URL。登录是通过 JS 表单提交完成的,因此在 ajax 部分中指定了 URL。成功后,还有另一个第三方身份验证方(okta)也将验证凭据并最终到达主页。那么我需要为我的任务调用真正的 API。

但它不起作用。

import requests
import sys
class Login:

     def sendRequestWithAuthentication(self,loginDetails,requestDetails):
         user_agent = {'User-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.129 Safari/537.36'}
         action_url=loginDetails['action_url'] if 'action_url' in loginDetails.keys() else None
         pay_load=loginDetails['payload'] if 'payload' in loginDetails.keys() else None
         session_requests = requests.session()
         if action_url and pay_load:
             act_resp=session_requests.post(action_url, data=pay_load, headers=user_agent,verify=False,files=[ ])
             print(act_resp)
             auth_cookies=act_resp.cookies.get_dict()
             url,method,request_payload = requestDetails['url'],requestDetails['method'],requestDetails['payload']
             querystring=requestDetails['querystring']
             response=session_requests.get(url,headers=user_agent,cookies=auth_cookies,data=request_payload,params=querystring)
             print(response)
             return response.json()

在上述动作中,URL 是在 ajax 部分中给出的 API,而在第二个请求中,URL 是该 GET 的 API 地址。

简而言之,我可以知道如何在 python 请求中实现多因素身份验证

我的疑惑

  1. 我们是否需要将登录表单页面中的 cookie 包含在登录请求中
  2. 如何在 python 请求中实现多因素身份验证(这里我们不需要任何 pin 或通过 RSA 完成的东西。)是否需要用于登录的证书,因为它现在无法验证 SSL 证书李>

给出一个实现这种场景的虚拟示例 api

【问题讨论】:

    标签: python python-requests


    【解决方案1】:

    不,你把它弄复杂了。这段代码有效:

    import requests
    
    login_url = "https://phpzag.com/demo/ajax_login_script_with_php_jquery/login.php"
    welcome_url = "https://phpzag.com/demo/ajax_login_script_with_php_jquery/welcome.php"
    
    payload = 'user_email=test@phpzag.com&password=test&login_button='
    login_headers = {
        'x-requested-with': 'XMLHttpRequest',
        'Content-Type': 'application/x-www-form-urlencoded', # its urlencoded instead of form-data
        'User-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.129 Safari/537.36',
    }
    s = requests.Session()
    login = s.post(login_url, headers=login_headers, data=payload) # post requests
    welcome = s.get(welcome_url, headers=login_headers)
    print(welcome.text)
    

    结果:

    .....Hello, <br><br>Welcome to the members page.<br><br>
    

    【讨论】:

      【解决方案2】:

      TL;DR

      将代码中显示data=payload 的部分更改为json=payload,它应该可以工作。

      直接回答您的问题

      [如何] 使用 Python 请求实现 [an] AJAX 请求?

      你不能那样做。 AJAX 请求特指基于 Javascript 的 HTTP 请求。引用W3 school's AJAX introduction page,“AJAX = 异步 JavaScript 和 XML”。

      间接回答您的问题

      我相信您要问的是如何使用流行的 python 包requests 执行身份验证/登录 HTTP 请求。简短的回答——不幸的是,和大多数事情一样——是视情况而定。不同的身份验证页面处理身份验证请求的方式不同,因此您可能需要执行不同的操作才能针对特定的 Web 服务进行身份验证。

      根据您的代码

      我将根据您的代码和response back from the server being a 406 error 含义做出一些假设,即登录页面可能正在寻找具有 JSON 对象形式的身份验证详细信息(例如凭据)的 POST 请求您发送的数据带有与服务器想要响应的方式不一致的接受标头。

      使用请求时,使用data参数到请求函数会发送数据“原始”;也就是说,它将以本机数据格式发送它(就像二进制数据的情况一样),或者如果该格式不起作用,它会将其转换为标准 HTML 表单数据(例如key1=value1&amp;key2=value2&amp;key3=value3,这种形式具有 application/x-www-form-urlencoded 的 MIME 类型,并且是当 data 未使用 accept 标头指定时发送的请求)。我将根据以下事实做出有根据的猜测:您将凭据放入字典中,即登录表单期待带有 JSON 格式正文的 POST 请求(大多数现代 Web 应用程序都这样做),并且您在印象中将data 参数设置为requests 会使它变成一个JSON 对象。这是一个常见的问题/误解,以前曾困扰过我的请求。您想要的是使用 json 参数传递数据。

      您的代码:

      from requests import Session
      import requests
      
      INDEX_URL = 'https://phpzag.com/demo/ajax_login_script_with_php_jquery/index.php'
      URL = 'https://phpzag.com/demo/ajax_login_script_with_php_jquery/welcome.php'
      LOGIN_URL = 'https://phpzag.com/demo/ajax_login_script_with_php_jquery/login.php' # Or whatever the login request url is
      payload = {'user_email': 'test@phpzag.com','password':'test'}
      
      s = requests.Session()
      user_agent = {'User-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.129 Safari/537.36'}
      t=s.post(LOGIN_URL, data=payload, headers=user_agent)
      r=s.get('https://phpzag.com/demo/ajax_login_script_with_php_jquery/welcome.php',headers=user_agent,cookies=t.cookies.get_dict())
      print(r.content)
      

      修复(和清理)代码:

      #!/usr/bin/env python3
      # -*- coding: utf-8 -*-
      """
         Test script to login to php web app.
      """
      
      import requests
      
      INDEX_URL = 'https://phpzag.com/demo/ajax_login_script_with_php_jquery/index.php'
      URL = 'https://phpzag.com/demo/ajax_login_script_with_php_jquery/welcome.php'
      LOGIN_URL = 'https://phpzag.com/demo/ajax_login_script_with_php_jquery/login.php' # Or whatever the login request url is
      
      payload = {
          'user_email': 'test@phpzag.com',
          'password':'test'
      }
      
      headers = {
          'User-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.129 Safari/537.36'
      }
      
      session = requests.Session()
      
      
      auth_response = session.post(
          url=LOGIN_URL,
          json=payload,  # <--- THIS IS THE IMPORTANT BIT. Note: data param changed to json param
          headers=user_agent
      )
      
      response = session.get(
          'https://phpzag.com/demo/ajax_login_script_with_php_jquery/welcome.php',
          headers=headers,
          cookies=auth_response.cookies.get_dict()  # TODO: not sure this is necessary, since you're using the session object to initiate the request, so that should maintain the cookies/session data throughout the session...
      )
      
      print(response.content)
      

      查看this section of the requests documentation on POST requests,如果您从那里向下滚动一点,您会看到文档讨论了需要 JSON 的 github API 以及如何处理它。

      总体而言,身份验证可能很棘手。有时事情会需要“基本身份验证”,这些请求会期望您将 tuple 作为 auth 参数传递,有时他们会想要一个不记名令牌/OAUTH 事情,这可能会让人头疼复杂/烦人.

      希望这会有所帮助!

      【讨论】:

      • 谢谢 - 这对我非常有帮助。虽然 ajax 网站上的身份验证对我来说是新的(我使用您的代码作为模板),但就您的#TODO 评论而言,我认为有必要在所有获取请求中包含 cookie,即使对于会话也是如此。请求文档表明 cookie 在这里不是持久的:requests.readthedocs.io/en/master/user/advanced
      • @thesimplevoodoo 不客气,很高兴我能帮上忙!有趣的。您可以随时尝试不添加 cookie,看看它是否有效。如果它不起作用(即您收到 403 错误等),那么您可以重新添加它。
      【解决方案3】:

      您缺少服务器(apache?)所需的用户代理

      试试这个:

      import requests
      from requests import Session
      
      URL = 'https://phpzag.com/demo/ajax_login_script_with_php_jquery/welcome.php'
      LOGIN_URL = 'https://phpzag.com/demo/ajax_login_script_with_php_jquery/login.php' # Or whatever the login request url is
      payload = {'user_email': 'test@phpzag.com','password':'test'}
      user_agent = {'User-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.129 Safari/537.36'}
      
      s = requests.Session()
      x=s.get(URL, headers=user_agent)
      x=s.post(LOGIN_URL, data=payload, headers=user_agent)
      print(x.content)
      print(x.status_code)
      

      【讨论】:

      • 结果还是一样,您可以通过访问phpzag.com/demo/ajax_login_script_with_php_jquery/index.php来重现我的问题
      • 但是 x.content 是空的。如何获取“phpzag.com/demo/ajax_login_script_with_php_jquery/welcome.php”的 HTML 内容作为输出
      • 您必须观看网络选项卡,然后使用会话 cookie 作为未来的标头,以跟随重定向到欢迎页面。正如您所说的那样,它是 ajax,然后页面逻辑正在执行此操作,但您可以通过查看网络选项卡来复制它。您的问题是用户代理。
      • 你是在暗示这个吗? p=s.post(LOGIN_URL, data=payload, headers=user_agent) x=s.get('https://phpzag.com/demo/ajax_login_script_with_php_jquery/welcome.php',header=p.header)
      • 我试过r=s.get('https://phpzag.com/demo/ajax_login_script_with_php_jquery/welcome.php',headers=x.cookies) 但结果是403作为响应
      【解决方案4】:

      看看Requests: Basic Authentication

      import requests
      
      requests.post(URL, auth=('user', 'pass'))
      
      # If there are some cookies you need to send
      cookies = dict(cookies_are='working')
      requests.post(URL, auth=('user', 'pass'), cookies=cookies)
      

      【讨论】:

      • 无法使用您可以通过https://phpzag.com/demo/ajax_login_script_with_php_jquery/index.php访问网站
      • @EdwardArrow 如果 cookie 被关闭并且 mod_security 需要 cookie 来匹配会话数据,则此错误将出现在某些站点中。它应该让事情更安全......它最终只是烦人。特别是因为像 googleBot 和其他搜索引擎这样的网络索引爬虫不使用 cookie,所以他们看到的是这个错误而不是你的网站。
      • 那么如何克服这个问题?
      • 你能帮我处理一下stackoverflow.com/questions/62044412/…@aldokkani
      • 我正在使用此方法进行 SSL 证书验证
      猜你喜欢
      • 1970-01-01
      • 2020-08-24
      • 2010-10-17
      • 2010-10-14
      • 2013-04-16
      • 2019-07-23
      • 2012-12-21
      • 2013-01-13
      • 1970-01-01
      相关资源
      最近更新 更多