Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to implement ajax request using Python Request

I'm trying to log into a website using Python request. Unfortunately, it is always showing this error when printing its content.

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>

For reference my code

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': '[email protected]','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)

May I know what is missing and how can I get HTML code of welcome page from this

UPDATE

I'm trying to get make an API call after login authentication. However, I'm not able to succeed in login authentication. Hence I am not able to get the response of API Call. As per my thought it due to multi-factor authentication it is getting failed. I need to know how can I implement this?

For eg: www.abc.com is the URL of the website. The login is done through JS form submission Hence URL is specified in the ajax part. On the success of that, there is another third authentication party(okta) which will also verify the credentials and finally reach the home page. then I need to call the real API for my task.

But it is not working.

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()

In the above action URL is the API given in the ajax part & in the second request, the URL is the API address for that GET.

In short, may I know how can implement multifactor authentication in python request

My Doubt

  1. Do we need the cookies from the login form page to include in the login request
  2. How to implement multifactor authentication in python request(Here we don't need any pin or something it is done through RSA.)Is there any need of a certificate for login as it now raising unable to validate the SSL certificate

Give a dummy example api that is implement such kind of scenario

like image 945
Aaditya R Krishnan Avatar asked May 05 '20 06:05

Aaditya R Krishnan


People also ask

Can we use AJAX in Python?

Another way of using Ajax in Django is to use the Django Ajax framework. The most commonly used is django-dajax which is a powerful tool to easily and super-quickly develop asynchronous presentation logic in web applications, using Python and almost no JavaScript source code.

How do I run a Python script from AJAX?

$. ajax({ type: 'POST', url: "scripts/sample.py", data: {param: xyz}, //passing some input here dataType: "text", success: function(response){ output = response; alert(output); } }). done(function(data){ console. log(data); alert(data); });

How does AJAX work in Python?

AJAX allows web pages to be updated asynchronously by exchanging data with a web server behind the scenes. This means that it is possible to update parts of a web page, without reloading the whole page.

Is it possible to make an Ajax request in Python?

You cannot do that. An AJAX request is specifically referring to a Javascript-based HTTP request. To quote from W3 school's AJAX introduction page, "AJAX = Asynchronous JavaScript And XML". What I believe you're asking is how to perform auth/login HTTP requests using the popular python package, requests.

How to make HTTP requests in Python?

GET: to request data from the server. POST: to submit data to be processed to the server. Here is a simple diagram which explains the basic concept of GET and POST methods. Now, to make HTTP requests in python, we can use several HTTP libraries like: httplib; urllib; requests. The most elegant and simplest of above listed libraries is Requests.

What are get and POST requests in Python?

This post discusses two HTTP (Hypertext Transfer Protocol) request methods GET and POST requests in Python and their implementation in python. What is HTTP? HTTP is a set of protocols designed to enable communication between clients and servers.

What is a GET request in an API?

An API (Application Programming Interface) enables you to access the internal features of a program in a limited fashion. And in most cases, the data provided is in JSON (JavaScript Object Notation) format (which is implemented as dictionary objects in Python!). The URL for a GET request generally carries some parameters with it.


Video Answer


3 Answers

No, you make it complex.This code worked:

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 = '[email protected]&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)

Result:

.....Hello, <br><br>Welcome to the members page.<br><br>
like image 95
jizhihaoSAMA Avatar answered Nov 04 '22 21:11

jizhihaoSAMA


TL;DR

Change the part of your code that says data=payload to json=payload, and it should work.

Direct answer to your question

How [does one] implement [an] AJAX request using Python Requests?

You cannot do that. An AJAX request is specifically referring to a Javascript-based HTTP request. To quote from W3 school's AJAX introduction page, "AJAX = Asynchronous JavaScript And XML".

Indirect answer to your question

What I believe you're asking is how to perform auth/login HTTP requests using the popular python package, requests. The short answer— unfortunately, and like most things—is that it depends. Various auth pages handle the auth requests differently, and so you might have to do different things in order to authenticate against the specific web service.

Based on your code

I'm going to make some assumptions that the login page is probably looking for a POST request with the authentication details (e.g. credentials) in the form of a JSON object based on your code, and based on the response back from the server being a 406 error meaning that you're sending data with an accept header that doesn't align with how the server wants to respond.

When using requests, using the data parameter to the request function will send the data "raw"; that is, it'll send it in the native data format it is (like in cases of binary data), or it'll translate it to standard HTML form data if that format doesn't work (e.g. key1=value1&key2=value2&key3=value3, this form has the MIME type of application/x-www-form-urlencoded and is what requests will send when data has not been specified with an accept header). I'm going to make an educated guess based on the fact that you put your credentials into a dictionary that the login form is expecting a POST request with a JSON-formatted body (most modern web apps do this), and you were under the impression that setting the data parameter to requests will make this into a JSON object. This is a common gotcha/misconception with requests that has bitten me before. What you want is instead to pass the data using the json parameter.

Your code:

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': '[email protected]','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)

Fixed (and cleaned up) code:

#!/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': '[email protected]',
    '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)

Check out this section of the requests documentation on POST requests, if you scroll down a bit from there you'll see the docs talk about the github API which expects JSON and how to handle that.

Auth can be tricky overall. Sometimes things will want "basic auth", which requests will expect you to pass as a tuple to the auth parameter, sometimes they'll want a bearer token / OAUTH thing which can get headache-inducing-ly complicated/annoying.

Hope this helps!

like image 25
masq Avatar answered Nov 04 '22 22:11

masq


You are missing the User agent that the server (apache?) requires

Try this:

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': '[email protected]','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)
like image 21
Luv Avatar answered Nov 04 '22 22:11

Luv