Python error "Connection reset by peer" in requests module - python-2.7

My goal is to create a persistent cookie on-the-fly by supplying user id & password and use that cookie in POST request using a session object. But below code returns below exception.
('Connection aborted.', error(54, 'Connection reset by peer'))
class CreatePersistentCookie(): """This class is created to generate a persistent cookie that can further be used through out session for all the service requests being executed"""
class CreatePersistentCookie():
"""This class is created to generate a persistent cookie that can further be
used through out session for all the service requests being executed"""
def __init__(self, headers, data, url, params, authserver):
self.headers = headers
self.data = data
self.url = url
self.params = params
self.authserver = authserver
def generateCookie(self):
with requests.session() as s:
reqsessionObj = s.post(self.authserver,params = self.params)
reqCookie = reqsessionObj.request.headers['Cookie'] # this returns the Cookie i need
regexObj = re.compile(r'act-uat=\S+') # this is my app specific pattern search that returns the exact cookie text i need.
matchObj = regexObj.search(reqCookie)
sessionCookie = matchObj.group()
self.headers['Cookie'] = sessionCookie # adding Cookie attribute in headers.
try:
r = s.post(self.url, data=json.dumps(self.data), headers=self.headers)
return r.raise_for_status()
except requests.exceptions.RequestException as err:
print err
def main():
# Defining the params variable. This contains authentication details such as user id,password & App id.
params = {"accountId": "John",
"accountPassword": "password",
"appIdKey": "5c9773e36fd6ea7cc2f9f8ffd9da3e3"
}
# Defining the authserver variable that contains the host details where authentication happens.
authserver = 'https://auth-uat.com/authenticate'
# creating a object cookieObj from class CreatePersistentCookie that returns persistent cookie.
#print cookies
headers = {'Content-Type': 'application/json;charset=UTF-8',
'Host':'service-uat1.com'}
data = {"appName":"abc","appKey":"abc","type":"jdbc","queryName":"xyz","version":"v1.2","useCache":"false","bindVars":[{"bindVarName":"In_dt","bindVarVal":"2014-05-13"},{"bindVarName":"In_Location","bindVarVal":"USA"}]}
url = 'https://uat1.com/gsf/abc/derf/abc/services/xyz'
cookieObj = CreatePersistentCookie(headers, data, url, params, authserver)
cookieObj.generateCookie()
if __name__ == '__main__':
main()

Connection reset by peer indicates that the server you're trying to connect to is refusing the connection. Normally, there is a handshake between your computer and the website's server, but here for some reason, the server is refusing the connection. I would use the urllib, requests, mechanize, and cookielib modules (some of which only work in Python 2.7). Then, using urllib you can attach a user-client header like Firefox, which will trick the browser into accepting the connection because they will think you are a regular person surfing the web, not a robot.

Try the below command in terminal it worked for me
pip install requests[security]

In my case it worked from Postman but not from python script. Restarting the system fixed it.

Related

Unable to send emails through Flask-mail

I have been trying to create a web app which takes email address as an input through HTML form and sends a one time pin for further access to website.
I have 2 html files in my template folder (one for taking user's email address and other for OTP entering)
i have config.json file which stores my accountid and password through which i intend to send the OTP.
.py file
from flask import Flask, render_template, request
from random import randint
import json
from flask_mail import *
with open('config.json','r') as f:
params = json.load(f)['params']
mail = Mail(app)
otp = randint(100,999) #otp production
app.config['MAIL_SERVER'] = 'smtp.gmail.com'
app.config['MAIL_PORT'] = 465
app.config['MAIL_USE_TLS'] = False
app.config['MAIL_USE_SSL'] = True
app.config['MAIL_USERNAME'] = params['gmail-user']
app.config['MAIL_PASSWORD'] = params['gmail-password']
#app.route('/')
def home():
return(render_template('otpgive.html'))
#app.route('/getOTP', methods = ['POST'])
def getOTP(): #OTP send and Verify here
email_id = request.form['usermail']
msg = Message('OTP for the APPLICATION', sender = 'my_email', recipients = [email_id])
#my_email is the email through which i plan to send messages.
msg.body = "Greetings! Your email has been verified successfully. Kindly note your OTP is " + str(otp)
mail.send(msg)
return render_template('otpconfirm.html')
#app.route('/validateOTP', methods = ['POST'])
def validateOTP():
userotp = request.form['otp']
if (otp == int(userotp)):
return ("Email Verified Succcessfully ")
else:
return render_template('otpgive.html',msg = 'incorrect otp')
if __name__ == '__main__':
app.run(debug = False)
#app.run(host='0.0.0.0',port=5000, debug = True)
Solutions I tried but failed:
Tried disabling the firewall.
Tried setting the port number for 0.0.0.0
Tried debug = False
I was expecting it to work. i.e send emails to the users but it shows ConnectionError or InternalServerError
Internal Server Error
The server encountered an internal error and was unable to complete your request. Either the server is overloaded or there is an error in the application.
ConnectionRefusedError:
[WinError 10061] No connection could be made because the target machine actively refused it
I finally got the solution.
Since I was using G-Mail, I had to enable 2FA (2-Factor Auth) first on my profile, and then generate a new password for my app.
The password thus obtained was pasted in the config.json file instead of my
main profile password.
Used directions from this thread Less Secure option in gmail unavailable
Now Changes I made in my code:
Reverted back to ip: host='0.0.0.0', port=5000, debug = True
I kept firewall disabled as a precaution.
I repositioned mail = Mail(app) line to after all app.configs

How to get Superset Token?? (for use Rest api)

I attempted to request a REST request to see the document below. But do not work. https://superset.apache.org/docs/rest-api
request: curl -XGET -L http://[IP:PORT]/api/v1/chart
response: {"msg":"Bad Authorization header. Expected value 'Bearer <JWT>'"}
The Superset installation has been on PIP and was also Helm Chart. But all are the same. helm: https://github.com/apache/superset
How should I order a REST API?
Check the security section of the documentation you have linked. It has this API ​/security​/login, you can follow the JSON parameter format and get the JWT bearer token. Use that token to send in the Header of your other API calls to superset.
open http://localhost:8080/swagger/v1, assuming http://localhost:8080 is your Superset host address
then find this section
the response would be like this
{
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJmcmVzaCI6dHJ1ZSwiaWF0IjoxNjU0MzQ2OTM5LCJqdGkiOiJlZGY2NTUxMC0xMzI1LTQ0NDEtYmFmMi02MDc1MzhjZDcwNGYiLCJ0eXBlIjoiYWNjZXNzIiwic3ViIjoxLCJuYmYiOjE2NTQzNDY5MzksImV4cCI6MTY1NDM0NzgzOX0.TfjUea3ycH77xhCWOpO4LFbYHrT28Y8dnWsc1xS_IOY",
"refresh_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJmcmVzaCI6ZmFsc2UsImlhdCI6MTY1NDM0NjkzOSwianRpIjoiNzBiM2EyZDYtNDFlNy00ZDNlLWE0NDQtMTRiNTkyNTk4NjUwIiwidHlwZSI6InJlZnJlc2giLCJzdWIiOjEsIm5iZiI6MTY1NDM0NjkzOSwiZXhwIjoxNjU2OTM4OTM5fQ.OgcctNnO4zTDfTgtHnaEshk7u-D6wOxfxjCsjqjKYyE"
}
Thank #andrewsali commented on this github issue, I finally figure out how to access the superset REST API by python code.
import requests
from bs4 import BeautifulSoup
import json
def get_supetset_session():
"""
# http://192.168.100.120:8088/swagger/v1
url = f'http://{superset_host}/api/v1/chart/'
r = s.get(url)
# print(r.json())
"""
superset_host = '192.168.100.120:8088' # replace with your own host
username = 'YOUR_NAME'
password = 'YOUR_PASSWORD'
# set up session for auth
s = requests.Session()
login_form = s.post(f"http://{superset_host}/login")
# get Cross-Site Request Forgery protection token
soup = BeautifulSoup(login_form.text, 'html.parser')
csrf_token = soup.find('input',{'id':'csrf_token'})['value']
data = {
'username': username,
'password': password,
'csrf_token':csrf_token
}
# login the given session
s.post(f'http://{superset_host}/login/', data=data)
print(dict(s.cookies))
return s
DEMO
# s = get_supetset_session()
base_url = 'http://192.168.100.120:8088'
def get_dashboards_list(s, base_url=base_url):
"""## GET List of Dashboards"""
url = base_url + '/api/v1/dashboard/'
r = s.get(url)
resp_dashboard = r.json()
for result in resp_dashboard['result']:
print(result['dashboard_title'], result['id'])
s = get_supetset_session()
# {'session': '.eJwlj8FqAzEMRP_F5z1Islay8jOLJcu0NDSwm5xK_r0uPQ7DG978lGOeeX2U2_N85VaOz1FuxVK6JIHu1QFhGuEOk5NG8qiYGkJ7rR3_Ym-uJMOzJqySeHhIG8SkNQK6GVhTdLf0ZMmG6sZGQtiQ1Gz0qYiUTVoHhohZthLXOY_n4yu_l0-VKTObLaE13i2Hz2A2rzBmhU7WkkN1cfdH9HsuZoFbeV15_l_C8v4F4nBC9A.Ypn16Q.yz4E-vz0gp3EmJwv-6tYIcOGavU'}
get_dashboards_list(s)
Thanks #Ferris for this visual solution!
To add to this, you can also create the appropriate API call with Python just like following:
import requests
api_url = "your_url/api/v1/security/login"
payload = {"password":"your password",
"provider":"db",
"refresh":True,
"username":"your username"
}
response = requests.post(api_url, json=payload)
# the acc_token is a json, which holds access_token and refresh_token
access_token = response.json()['access_token']
# no get a guest token
api_url_for_guesttoken = "your_url/api/v1/security/guest_token"
payload = {}
# now this is the crucial part: add the specific auth-header
response = request.post(api_url_for_guesttoken , json=payload, headers={'Authorization':f"Bearer {access_token}"})

Authentication with GitLab to a terminal

I have a terminal that served in webbrowser with wetty. I want to authenticate the user from gitlab to let user with interaction with the terminal(It is inside docker container. When user authenticated i ll allow him to see the containers terminal).
I am trying to do OAuth 2.0 but couldn't manage to achieve.
That is what i tried.
I created an application on gitlab.
Get the code and secret and make a http call with python script.
Script directed me to login and authentication page.
I tried to get code but failed(Their is no mistake on code i think)
Now the problem starts in here. I need to get the auth code from redirected url to gain access token but couldn't figure out. I used flask library for get the code.
from flask import Flask, abort, request
from uuid import uuid4
import requests
import requests.auth
import urllib2
import urllib
CLIENT_ID = "clientid"
CLIENT_SECRET = "clientsecret"
REDIRECT_URI = "https://UnrelevantFromGitlabLink.com/console"
def user_agent():
raise NotImplementedError()
def base_headers():
return {"User-Agent": user_agent()}
app = Flask(__name__)
#app.route('/')
def homepage():
text = 'Authenticate with gitlab'
return text % make_authorization_url()
def make_authorization_url():
# Generate a random string for the state parameter
# Save it for use later to prevent xsrf attacks
state = str(uuid4())
save_created_state(state)
params = {"client_id": CLIENT_ID,
"response_type": "code",
"state": state,
"redirect_uri": REDIRECT_URI,
"scope": "api"}
url = "https://GitlapDomain/oauth/authorize?" + urllib.urlencode(params)
print get_redirected_url(url)
print(url)
return url
# Left as an exercise to the reader.
# You may want to store valid states in a database or memcache.
def save_created_state(state):
pass
def is_valid_state(state):
return True
#app.route('/console')
def reddit_callback():
print("-----------------")
error = request.args.get('error', '')
if error:
return "Error: " + error
state = request.args.get('state', '')
if not is_valid_state(state):
# Uh-oh, this request wasn't started by us!
abort(403)
code = request.args.get('code')
print(code.json())
access_token = get_token(code)
# Note: In most cases, you'll want to store the access token, in, say,
# a session for use in other parts of your web app.
return "Your gitlab username is: %s" % get_username(access_token)
def get_token(code):
client_auth = requests.auth.HTTPBasicAuth(CLIENT_ID, CLIENT_SECRET)
post_data = {"grant_type": "authorization_code",
"code": code,
"redirect_uri": REDIRECT_URI}
headers = base_headers()
response = requests.post("https://MyGitlabDomain/oauth/token",
auth=client_auth,
headers=headers,
data=post_data)
token_json = response.json()
return token_json["access_token"]
if __name__ == '__main__':
app.run(host="0.0.0.0",debug=True, port=65010)
I think my problem is on my redirect url. Because it is just an irrelevant link from GitLab and there is no API the I can make call.
If I can fire
#app.route('/console')
that line on Python my problem will probably will be solved.
I need to make correction on my Python script or different angle to solve my problem. Please help.
I was totally miss understand the concept of auth2. Main aim is to have access_token. When i corrected callback url as localhost it worked like charm.

flask-jwt-extended gives same token all the time for /login requests

jwt-flask-extended sends back same access token for any user always. I have integrated Flask with apache. Using Python 2.7.5, Operating System - Red Hat Enterprise Linux Server release 7.3 (Maipo). Find the code below.
app = Flask(__name__)
CORS(app)
#app.before_request
def log_request_info():
app.logger.debug('Headers: %s', request.headers)
app.logger.debug('Body: %s', request.get_data())
mysql = MySQL()
# MySQL configurations
app.config['MYSQL_DATABASE_USER'] = 'user'
app.config['MYSQL_DATABASE_PASSWORD'] = 'password'
app.config['MYSQL_DATABASE_DB'] = 'userdb'
app.config['MYSQL_DATABASE_HOST'] = 'mysql-host'
mysql.init_app(app)
# Setup the Flask-JWT-Extended extension
app.config['JWT_SECRET_KEY'] = 'Changeit' # Change this! if needed
app.config['JWT_EXPIRATION_DELTA'] = timedelta(seconds=28800)
jwt = JWTManager(app)
#app.route('/auth/token', methods=['POST'])
def login():
if not request.is_json:
return jsonify({"msg": "Missing JSON in request"}), 400
uid = request.json.get('uid', None)
username = request.json.get('username', None)
if not uid:
return jsonify({"msg": "Missing required parameter"}), 400
if not username:
return jsonify({"msg": "Missing required parameter"}), 400
# Identity can be any data that is json serializable
access_token = create_access_token(identity=uid)
return jsonify(access_token=access_token), 200
WSGIPassAuthorization On.
I added this directive to Apache mod wsgi config file. It started working as expected .
That's because you're using global variables which aren't thread safe.
Your access token variable should go inside a function or a method.
If you still want it globally accessible, you can use Werkzeug's local package along with Flask's g variable.
I recommend putting it in a method though.

python web py automated testing

I am having an issue with automated testing in web py framework.
I am going through the last exercise of learn python the hard way. In this exercise we make a web application "engine" that runs a map of rooms.
I want to be able to automate test every single room, but there is one problem, is that the engine depends on the previous room to decide which room to go to next (and user input).
if web.config.get("_session") is None:
store = web.session.DiskStore("sessions")
session = web.session.Session(app, store, initializer={"room":None})
web.config._session = session
else:
session = web.config._session
This class handles GET request sent to /
class Index(object):
def GET(self):
session.room = map.START
web.seeother("/game")
This class handles GET and POST requests to /game
class GameEngine(object):
def GET(self):
if session.room:
return render.show_room(room=session.room)
else:
return render.you_died()
def POST(self):
form = web.input(action=None)
if session.room and form.action:
session.room = session.room.go(form.action)
web.seeother("/game")
In my automated testing I use two things: first I use the app.request API:
app.request(localpart='/', method='GET',data=None,
host='0.0.0.0:8080', headers=None, https=False)
create a response object, something like:
resp = app.request("/game", method = "GET")
Second I pass the resp object to this function to check for certain things:
from nose.tools import *
import re
def assert_response(resp, contains=None, matches=None, headers=None,
status="200"):
assert status in resp.status, "Expected response %r not in %r" %
(status, resp.status)
if status == "200":
assert resp.data, "Response data is empty"
if contains:
assert contains in resp.data, "Response does not contain %r" %
contains
if matches:
reg = re.compile(matches)
assert reg.matces(resp.data), "Response does not match %r" %
matches
if headers:
assert_equal(resp.headers, headers)
We can pass variables as a dictionary to the keyword argument data in the API app.request to modify the web.input().
my question is: in my automated test module how do we "pass" a value that overwrite the room value in the initializer dictionary in our session:
session = web.session.Session(app, store, initializer={"room":None})
In the app module its done by setting
session.room = map.START
and then session.room updates using:
if session.room and form.action:
session.room = session.room.go(form.action)
Thanks for taking the time to read this, and any insights would be appreciated!
Alright I finally found it! The main issue here was that every time I make a http request through app.request it gives me a new session ID.
The trick that I found thanks to this post:
How to initialize session data in automated test? (python 2.7, webpy, nosetests)
is to record the session ID of the request to reuse that ID in my automated tests by passing it to the headers keyword argument in the request!
record the session ID using this function (which I placed as suggested in the post in tests/tools.py):
def get_session_id(resp):
cookies_str = resp.headers['Set-Cookie']
if cookies_str:
for kv in cookies_str.split(';'):
if 'webpy_session_id=' in kv:
return kv
then in the automated tests something like:
def test_session():
resp = app.request('/')
session_id = get_session_id(resp)
resp1 = app.request('/game', headers={'Cookie':session_id})
assert_response(resp1, status='200', contains='Central Corridor')
I hope that helps in the future for programmers who get stuck on the same issue!