The problem with saving the session without using a browser (using python.requests).

281 views
Skip to first unread message

Владимир Пылев

unread,
Mar 2, 2020, 3:04:23 PM3/2/20
to Django users
Hello! In my situation, I need to communicate with the django application through python from the desktop application (using python.requests).

The logic is this:
1 - Transfer the username and password to the login() - get and save to file the session_id.
2 - Use session_id from file to identify user for get() and post() requests. In order not to transfer login and password every time.
3 - Before each post() request, I make a get() request to get a CSRF code.

What i get:
If you use a fresh session_id (without saving to a file) then everything works.
And if you use session_id from a file, then the user is identified only for get() requests. For post() requests, the user is not identified.

So the question is:
What am I doing wrong, or should it be so?

Code examples:

# In myApp/views.py

def db_login(request):
   
if request.method == 'POST':
        user
= authenticate(request, username=request.POST.get('username'),  password=request.POST.get('password'))
       
if user is not None:
            login
(request, user)
           
return HttpResponse(json.dumps([True, "Logged In", dict(request.headers), request.user.username ]))
       
else:
           
return HttpResponse(json.dumps(False, "Not Logged In"))
   
else:
        get_token
(request) # adding csrftoken in cookies.
       
return HttpResponse(json.dumps([request.method, request.user.username ]))


def studio_create(request):
   
if request.method == 'POST':
       
return HttpResponse(json.dumps((request.method, dict(request.headers), request.user.is_authenticated, request.user.username )))
   
   
else:
        get_token
(request) # adding csrftoken in cookies.
       
return HttpResponse(json.dumps((request.method, dict(request.headers), request.user.is_authenticated, request.user.username )))


The case when everything works, when the user was identified by session_id when executing a post() request:

# In Desktop app

import requests

def post_var1():
    create_url
=f'{HOST}db/studio/create/'
    login_url
=f'{HOST}db/login/'
    cookie_path
= '/tmp/cookie'


   
# (1.0) get to login()
    sess
= requests.Session()
    r1
=sess.get(login_url)
   
# (1.1) post to login()
    csrf_token
= r1.cookies.get('csrftoken')
    r2
= sess.post(login_url, data=dict(username='vofka', password='1234', csrfmiddlewaretoken=csrf_token))
   
# (1.2) write cookie
   
with open(cookie_path, 'w') as f:
        f
.write(json.dumps(dict(r2.cookies)))
       
   
# (2.0) get to create()
    sessionid
= r2.cookies.get('sessionid')
    r3
=sess.get(create_url, cookies = dict(sessionid=sessionid))
   
# (2.1) post to create()
    csrf_token
= r3.cookies.get('csrftoken')
    r4
=sess.post(create_url, data=dict(csrfmiddlewaretoken=csrf_token, cookies=dict(sessionid=sessionid)))
       
   
print(r4.json())


>> ["POST", {"Content-Length": "102", "Content-Type": "application/x-www-form-urlencoded", "Host": "localhost:8000", "User-Agent": "python-requests/2.23.0", "Accept-Encoding": "gzip, deflate", "Accept": "*/*", "Connection": "keep-alive", "Cookie": "csrftoken=JXTlxGsCPzj6LbeOfJwYJ2A2OYnVEucEp1WhhCF6C4ML2gGs4kJrOQEuXgm9SFSJ; sessionid=vuhkhofnxeh485ar0rocfnotdttmfbp3"}, true, "vofka"]

The case when session_id from a file are used. And the user is identified only for get() requests.

# In Desktop app

import requests


def post_var2():
    url
=f'{HOST}db/studio/create/'
    html
= '/tmp/mtest.html'
    cookie_path
= '/tmp/cookie'
   
   
# (1) read cookie
   
with open(cookie_path, 'r') as f:
        cookie
=json.load(f)
   
   
# (2) get to create()
    sess
= requests.Session()
    r3
=sess.get(url, cookies = cookie)
   
   
# (3) post to create()
    csrf_token
= r3.cookies.get('csrftoken')
    r4
=sess.post(url, data=dict(csrfmiddlewaretoken=csrf_token, cookies=cookie ))
   
>> print(r3.json())
>> ['GET', {'Content-Length': '', 'Content-Type': 'text/plain', 'Host': 'localhost:8000', 'User-Agent': 'python-requests/2.23.0', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-alive', 'Cookie': 'csrftoken=JXTlxGsCPzj6LbeOfJwYJ2A2OYnVEucEp1WhhCF6C4ML2gGs4kJrOQEuXgm9SFSJ; sessionid=vuhkhofnxeh485ar0rocfnotdttmfbp3'}, True, 'vofka']

>> print (r4.json())
>> ['POST', {'Content-Length': '120', 'Content-Type': 'application/x-www-form-urlencoded', 'Host': 'localhost:8000', 'User-Agent': 'python-requests/2.23.0', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-alive', 'Cookie': 'csrftoken=JXTlxGsCPzj6LbeOfJwYJ2A2OYnVEucEp1WhhCF6C4ML2gGs4kJrOQEuXgm9SFSJ'}, False, '']


Django version 3.0.3 Python version 3.7.6

settings.MIDDLEWARE did not change from the creation of the project with the startproject command:
# In settings.py

MIDDLEWARE
= [
   
'django.middleware.security.SecurityMiddleware',
   
'django.contrib.sessions.middleware.SessionMiddleware',
   
'django.middleware.common.CommonMiddleware',
   
'django.middleware.csrf.CsrfViewMiddleware',
   
'django.contrib.auth.middleware.AuthenticationMiddleware',
   
'django.contrib.messages.middleware.MessageMiddleware',
   
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]


Владимир Пылев

unread,
Mar 4, 2020, 8:21:45 AM3/4/20
to Django users
Solution found. For some reason, you must pass the cookie to the session object itself.

sess = requests.Session()
cj
=requests.utils.cookiejar_from_dict(cookie)
sess
.cookies=cj

In this post() and get() requests I did not change:

# (3) get to create
r3
=sess.get(url, cookies = cookie)
   
# (4) post to create

csrf_token
= r3.cookies.get('csrftoken')
r4=sess.post(url, data=dict(csrfmiddlewaretoken=csrf_token, cookies=cookie ))



понедельник, 2 марта 2020 г., 23:04:23 UTC+3 пользователь Владимир Пылев написал:
Reply all
Reply to author
Forward
0 new messages