用 Django 的 session 验证机制也可以做到前后端的完全分离

用 Django 的 session 验证机制也可以做到,前后端的完全分离。当然本文只是为了证明可行性,在实际生产环境中,对于前后端完全分离, 主流的认证机制是 token 或 JWT token。从回答下面的问题,引出咱们的正题。

Django 整个认证过程中,从后端到前端, session id是怎么被触发写入cookie 的?
后端代码调用 response.set_cookie() 就会在响应头里写 Set-Cookie: sessionid=xxxx;Max-Age=1209600;Path=/ ,
浏览器收到响应且解析响应头发现有 Set-Cookie,则就会触发自己写 cookie 也会把 Max-Age、Path 等信息写入cookie,然后在下次请求该domain的相关 URL 的时候把 cookie 带上, 这是浏览器自动的行为。

所以如果要用代码模拟浏览器的行为,就需要手动解析响应头,然后把这些信息自己保存起来比如写文件里,最后下次请求的时候,带上这些信息。(代码中可以调用 get_sessionid 去真正的获取 seesionid 然后再和业务接口通信, 当然也可以修改下 django_session 表里的数据同时把伪造的 sessionid 拿到放到 cookie 中,也就可以和业务接口通信了), 请参考: 下面的代码

import requests
import json
def get_sessionid():
    input_dict = {'username': 'admin', 'password': 'start01all'}
    url = 'http://192.168.56.101:8082/myself_login/'
    
    # 参考 https://blog.csdn.net/cpxsxn/article/details/98184681 避开 CSRF 的限制
    # res = requests.post(url, data=input_dict, allow_redirects=False)
    res = requests.post(url, data=input_dict, allow_redirects=False,
                        headers={'X-CSRFToken': 'mycsrftokenabc', 'Cookie': 'csrftoken=mycsrftokenabc'})
    print 'type(res.headers) = {0}, res.headers = {1}'.format(type(res.headers), res.headers)
    print 'type(res.text) = {0}, res.text = {1}'.format(type(res.text), res.text)
    print 'res.status_code = {0}'.format(res.status_code)
    var_cookie = res.headers.get('Set-Cookie')
    print 'var_cookie = {0}'.format(var_cookie)
    tmp_list = var_cookie.split(';')
    print '----------------------------'
    for item in tmp_list:
        if item.find('sessionid') != -1:
            session_related_info = item.split(',')
            for data in session_related_info:
                print 'session_relataed data = {0}'.format(data)
                if data.find('sessionid') != -1:
                    sessionid = data.split('=')[1]
    return sessionid

# 可以调用 get_sessionid 去真正的获取 seesionid 然后再和业务接口通信, 其中会涉及避开 CSRF 的限制
# 当然也可以修改下 django_session 表里的数据同时把伪造的 sessionid 拿到放到 cookie 中,也就可以和业务接口通信了
url = 'http://192.168.56.101:8082/data/student_data/'
# sessionid = get_sessionid()
sessionid = 'tvh1n5j5n22spesiq9mtvph5llkwl2c01'
print 'sessionid = {0}'.format(sessionid)
cookie = 'csrftoken=mycsrftokenabc;sessionid={0}'.format(sessionid)
res = requests.get(url,params={'user':'robert'}, headers={'X-CSRFToken': 'mycsrftokenabc', 'Cookie': cookie})
print res.text

进阶:
后来发现 request 包有 session 函数,恍然大悟原来一切都有现成的包,于是:

>>> import requests
>>> 
>>> url = 'http://192.168.56.101:8082/myself_login/'
>>> input_dict = {'password': 'start01all', 'username': 'admin'}
>>> s = requests.session()
>>>
>>> Case 1:
>>> res = s.post(url, data=input_dict,headers={'X-CSRFToken': 'mycsrftokenabc', 'Cookie': 'csrftoken=mycsrftokenabc'}, allow_redirects=False)
>>>
>>> res.cookies   
<RequestsCookieJar[Cookie(version=0, name='csrftoken', value='lJif1y7X2w110MlDXsegTbdoC5GNBS0J', port=None, port_specified=False, domain='192.168.56.101', domain_specified=False, domain_initial_dot=False, path='/', path_specified=True, secure=False, expires=1606134216, discard=False, comment=None, comment_url=None, rest={}, rfc2109=False), Cookie(version=0, name='rob_testcookie', value='robert', port=None, port_specified=False, domain='192.168.56.101', domain_specified=False, domain_initial_dot=False, path='/', path_specified=True, secure=False, expires=None, discard=True, comment=None, comment_url=None, rest={}, rfc2109=False), Cookie(version=0, name='sessionid', value='3k6e9t52ki988eslyfwc63d0taswd82o', port=None, port_specified=False, domain='192.168.56.101', domain_specified=False, domain_initial_dot=False, path='/', path_specified=True, secure=False, expires=1575894216, discard=False, comment=None, comment_url=None, rest={'httponly': None}, rfc2109=False)]>
>>> 
>>> 
>>> Case 2: 把 case 1 中的 allow_redirects 参数去掉即设置为 True, 注意看后端日志都会有重定向 url  /hello 的请求;同时由于 /hello 的视图函数并不会写 cookie, 所以 print res.cookies 会打印为空
>>> res = s.post(url, data=input_dict,headers={'X-CSRFToken': 'mycsrftokenabc', 'Cookie': 'csrftoken=mycsrftokenabc'})
>>> 
>>> res.cookies
<RequestsCookieJar[]>
>>> 
发布了44 篇原创文章 · 获赞 0 · 访问量 3941

猜你喜欢

转载自blog.csdn.net/cpxsxn/article/details/102884805
今日推荐