Django会话机制
Django中默认支持Session,Django有一个会话框架来处理Cookies。使用之前,需要配置下Django 的缓存框架。可以通过settings.py中的MIDDLEWARE_CLASSES和INSTALLED_APPS进行Session设置。
1 | INSTALLED_APPS = ( |
Django内部提供了5种类型的Session供开发者使用,通过在 settings.py 中增加 SESSION_ENGINE 配置实现
数据库(默认):SESSION_ENGINE =’django.contrib.sessions.backends.db’ Django 默认是将 Session 数据存储在数据库中,即:django_session 表中。
1
2
3
4
5
6
7
8
9
10# 配置settings.py
SESSION_ENGINE = 'django.contrib.sessions.backends.db' # 引擎(默认)
SESSION_COOKIE_NAME = "sessionid" # Session的cookie保存在浏览器上时的key, 即:sessionid=随机字符串(默认)
SESSION_COOKIE_PATH = "/" # Session的cookie保存的路径(默认)
SESSION_COOKIE_DOMAIN = None # Session的cookie保存的域名(默认)
SESSION_COOKIE_SECURE = False # 是否Https传输cookie(默认)
SESSION_COOKIE_HTTPONLY = True # 是否Session的cookie只支持http传输(默认)
SESSION_COOKIE_AGE = 1209600 # Session的cookie失效日期(2周)(默认)
SESSION_EXPIRE_AT_BROWSER_CLOSE = False # 是否关闭浏览器使得Session过期 (默认)
SESSION_SAVE_EVERY_REQUEST = False # 是否每次请求都保存Session,默认修 改之后才保存(默认)缓存:SESSION_ENGINE = ‘django.contrib.sessions.backends.cache’ 需要快速存储会话的场景,可以选择将 Session 保存到缓存中。 这种配置方案 Django 只是简单保存会话。同时,这种方案持久性不好。因为当缓存 数据存满时将清除部分数据,或者遇到缓存服务器重启时数据将丢失。
1
2
3
4# 配置settings.py
SESSION_ENGINE = 'django.contrib.sessions.backends.cache' # 引擎
SESSION_CACHE_ALIAS = 'default' # 使用的缓存别名(默认内存缓存,也可以 是memcache),此处别名依赖缓存的设置
# 其他配置与db方式一致文件:SESSION_ENGINE = ‘django.contrib.sessions.backends.file’
这种方案是保存数据到本地磁盘中。因为磁盘的 I/O 瓶颈问题,导致这种方案存储数 据效率不是很高。
可选配置:SESSION_FILE_PATH = ‘/monkey/www/‘
SESSION_FILE_PATH 默认使用 tempfile.gettempdir() 方法的返回值,就像 /tmp 目录。
如果你想更新文件的保存路径,可以手动指定。另外需确保你的文件存储目录,以及 Web 服务器对该目录具有读写权限。
1
2
3
4
5# 配置settings.py
SESSION_ENGINE = 'django.contrib.sessions.backends.file' # 引擎
SESSION_FILE_PATH = None # 缓存文件路径,如果为None,则使用tempfile模块获 取一个临时地址tempfile.gettempdir()
# 如:/var/folders/d3/j9tj0gz93dg06bmwxmhh6_xm0000gn/T
# 其他配置与db方式一致缓存+数据库:SESSION_ENGINE = ‘django.contrib.sessions.backends.cached_db’
这种方案既保证快速存储会话数据,又保证数据持久性。因为该使用方案,Session 在保存到缓存的同时还会被保存到数据库中,当 Django 在缓存中找不到Session 时,会从数据库中找到。因此,这种方案的性能开销会比较大。
如果我们在工程中同时配置了数据库会话和缓存会话,Django 默认优先选择缓存会话。
1
2
3# 配置settings.py
SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db' # 引擎
# 其他配置与db方式一加密 cookie:SESSION_ENGINE = ‘jango.contrib.sessions.backends.signed_cookies’
这种方案将数据保存到 cookie 中。这种方案适用于对数据保密性不严格的场景。另外,建议增加配置SESSION_COOKIE_HTTPONLY= True,阻止 javascript 对会话数据的访问,提高安全性。
1
2
3# 配置settings.py
SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies' # 引擎
# 其他配置与db方式一
Cookie常用方法:
常用方法 | 说明 |
---|---|
set_cookie | response.set_cookie(“cookie_key”,”value”) #设置Cookies red.set_cookie(‘username’, u) #将用户名插入cookie |
delete_cookie | response.delete_cookie(“cookie_key”,path=”/“,domain=name) 删除Cookies |
COOKIES | value = request.COOKIES[“cookie_key”] # 获取Cookies if “cookie_name” is request.COOKIES : # 检测Cookies user = request.COOKIES.get(‘username’) #从cookie中取值 |
set_signed_cookie | \rep.set_signed_cookie(key,value,salt=’加密盐’,…) 参数: key, 键 value=’’, 值 max_age=None, 超时时间,表示多少秒数之后失效 expires=None, 超时时间,表示失效的时间点。支持datetime 和 time.time path=’/‘, Cookie生效的路径,/ 表示根路径,特殊的:跟路 径的cookie可以被任何url的页面访问 domain=None, Cookie生效的域名 secure=False, https传输 httponly=False 只能http协议传输,无法被JavaScript获取(不是 绝对,底层抓包可以获取到也可以被覆盖) 由于cookie保存在客户端的电脑上,所以,JavaScript和jquery也可以操作cookie。 <script src=’/static/js/jquery.cookie.js’></script> $.cookie(“list_pager_num”, 30,{ path: ‘/‘ }); |
get_signed_cookie | request.get_signed_cookie(key, default=RAISE_ERROR, salt=’’, max_age=None) |
1 | from django.shortcuts import render,redirect |
运行django之后,访问index,会自动跳转到login页面,输入账户密码之后,自动跳转到index,并从cookie中取出username,打印出来 。
**Session常用方法: **
常用方法 | 说明 |
---|---|
request.session[‘k1’] | 获取session,如果没有会报错 |
request.session.get(‘k1’,None) | 获取session,如果没有会返回None |
request.session[‘k1’] = 123 | 设置session,如果k1存在就覆盖 |
request.session.setdefault(‘k1’,123) | 设置session,如果不存在则创建默认值,存在则不设置 |
del request.session[“k1”] | 只删除k1,随机字符串和其他session值还存在 |
request.session.session_key | 获取session字符串 |
request.session.clear_expired() | 将所有Session失效日期小于当前日期的数据删除 |
request.session.exists(“session_key”) | 检查用户session的随机字符串 在数据库中是否存在 |
request.session.delete(“session_key”) | 删除当前用户的所有Session数据 |
request.session.clear() | 清除用户的所有session数据,用于注销 |
request.session.set_expiry(value) | 设置session超时时间,默认2周 # 如果value是个整数,session会在value秒后失效 # 如果value是个datatime或timedelta,session会在这个时间后失效 # 如果value是0,用户关闭游览器session会失效 # 如果value是None,session会依赖全局session失效策略 |
request.session.keys() | 提取所有键 |
request.session.values() | 提取所有值 |
request.session.iterkeys() | 迭代键 |
request.session.itervalues() | 迭代值 |
request.session.iteritems() | 迭代键值 |
示例:
1 | def session_login(request): |
测试点
会话生成
检查会话标识(sessionid)是否使用安全随机数算法生成,且有效长度不少于 24 个字 符(或 192bits);
如果使用 Django 内置的会话管理系统,会话标识符强且随机,可以无需测试。
会话超时
检查 settings.py 中会话相关的配置,是否设置了会话超时时间,超时过后必须要清除该会话信息;
超时时间根据业务进行设定,建议设置为 10 分钟。
正确的配置参考:
1 | SESSION_COOKIE_AGE = 1209600 # Session的cookie失效日期(2周)(默认) |
会话固定
获取代码,搜索关键字“response.set_cookie”,检查用户成功登录后,系统是否更换会 话标识,重新设置了 sessionid,如果没有,则存在会话固定漏洞;
使用 Django 内置的会话管理系统,可以免受会话固定攻击。
安全属性配置
检查 settings.py 中 SESSION_ENGINE 的配置,是否设置了 PATH、DOMAIN、SECURE 和 HTTPONLY;其中,SECURE 和 HTTPONLY 必须设置为 True,其他根据实际业务进行设置:
1 | SESSION_COOKIE_PATH = "/" # Session的cookie保存的路径(默认) |
设置了安全属性secure和httponly之后,能防止会话劫持,以及其他因无意使用HTTP发送敏感Cookie而造成的攻击。
会话保存
Django内部提供了5种类型的Session供开发者使用,通过在 settings.py 中增加 SESSION_ENGINE 配置实现。参考之前的介绍。
首先检查 settings.py 文件中 SESSION_ENGINE 的配置,判断使用了哪种方式保存 session 信息,如果使用 signed_cookies,则存在安全风险,建议整改;
会话加密传输
检查是否使用加密方式传输会话信息(建议使用 HTTPS,TLS 加密) ;
会话清除
找到 LOGOUT 接口,搜索关键字“request.session.delete(“session_key”)”,检查用户主动 退出时,服务器端是否清除该用户的会话信息;
检查会话超时后,系统是否主动清除用户的会话信息;