Monday, March 2, 2020

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

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',
]


--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/4ff0c2cf-932d-4d8c-9cbf-1453ebefc4fe%40googlegroups.com.

No comments:

Post a Comment