django框架之cookie/session的使用示例(小结)


Posted in Python onOctober 15, 2018

一、http协议无状态问题

http协议没有提供多次请求之间的关联功能,协议的本意也并未考虑到多次请求之间的状态维持,每一次请求都被协议认为是一次性的。但在某些场景下,如一次登录多次访问,我们希望可以保存登录状态,协议并没有直接提供会话跟踪的支持,需要靠其他手段来帮助实现目标。

二、会话跟踪技术--cookie

1、对cookie的理解

  • cookie是一个key-value的数据结构(类似python字典),用于保存需要维护状态的数据,cookie与session最大的区别是cookie的数据保存在客户端,而session把数据保存在服务端。
  • cookie一般由服务器设置,并可以存放在http的请求头和响应头中。
  • cookie由浏览器保存,浏览器已经实现了cookie的保存和发送,而服务器上对cookie的设置和接收则需要我们配置。
  • 通过cookie,可以在多个会话之间共享一些必要的信息如登录状态数据、历史访问记录、个性化定制设置等,以实现会话跟踪,让用户感觉到网站可以'记录'自己的偏好,减少不必要的重复输入,从而提升用户体验。

2、cookie的使用接口

django的服务端发送响应有三种方式:
1. return HttpResponse()
2. return render()
3. return redirect()

这三种方法实例化的结果都是HttpResponse类的实例,可以直接用于设置cookie。

在response对象上执行set_cookie(key,value,...)即可设置cookie, 其中特别注意cookie属性的设置。

cookie的设置

服务器在响应对象上进行set_cookie操作,一旦设置完成,客户端后续的请求就可以根据cookie的属性规则携带cookie数据。

def set_cookie(key, value='', max_age=None, expires=None, path='/',
        domain=None, secure=False, httponly=False, samesite=None)

cookie的获取

服务器在请求对象上通过request.COOKIES得到cookie字典数据,注意此处拿到的cookie数据从安全性来说是未被验证正确性的。

@cached_property
def COOKIES(self):
  raw_cookie = get_str_from_wsgi(self.environ, 'HTTP_COOKIE', '')
  return parse_cookie(raw_cookie)

注意1:cookie在set的时候可以设置它被发送的范围,每个cookie都有对应的domain+path的属性,这约束了cookie发送范围,只有当http的请求落在此范围中的url,才会携带此cookie。

注意2:一个cookie就是一个key-value项,不过它还携带有属性。一个cookies是一个字典,保存了很多cookie项,注意单个cookie项和整个cookies字典的关系。

3、cookie的属性

max_age:
失效延迟时间,单位是秒,设置成15秒意味着在设置完之后的15秒之内,此cookie有效,超时之后cookie失效,浏览器会删除失效的cookie。此参数默认是None,代表着直到浏览器关闭,即默认是会话cookie。
注意:如果max_age是0,意味着让浏览器立刻删除此cookie,即此cookie即刻失效。

expires:
指定失效日期,同样用于失效cookie,只不过是另一种时间指定方式。

domain:
此cookie可以被使用的域名范围。

path:
与domain配合着使用,默认是根路径'/',意味着在当前domain范围下任何url都会携带此cookie。可以主动设置其他的路径以缩小发送的范围,从而约束某一个cookie项只应用于某些url。

secure:
默认是False,一般配合https协议使用,在https协议下,只有secure属性是True的cookie才允许被发送。

httponly:
默认是False,这意味着js也可以通过document.cookie来访问和设置此cookie,而如果设置为True,则代表只允许服务端来访问和设置此cookie。

4、使用cookie的问题

cookie的安全性问题

服务器是根据客户端发送过来的cookie进行状态判断,这种保存在客户端的cookie数据非常容易修改和伪装,服务器基本无法知晓cookie的正确性,也就不能100%信任cookie的数据。

此外,cookie很容易被盗取,如果客户端cookie里面包含私密数据的话,就更不安全了。

cookie的覆盖问题

在服务端上设置的新的cookie会让客户端更新本地cookie。

cookie的合理性问题

什么样的数据适合放到cookie中?

cookie中的数据是每次交互都要被传输的,所以我认为:

  • 应该是常用的数据,如果不常用只会浪费带宽减少效率,最好是多次交互中都要使用或者修改
  • 应该是小数据量
  • 不应该是非常私密的数据,否则:要么在客户端上容易被盗取,要么在传输中容易被截取

所以cookie特别适合发送sessionid,它能满足上述所有条件。

cookie的存储问题

cookie是客户端临时存储,按规定单个cookie文件存储量最大是4kb,每个域下的cookie文件不能超过20个,不应该将cookie作为存储功能的滥用,要使用客户端存储功能应该启用localstorage。

cookie的访问限制问题

js的document.cookie可以获取cookie数据,将会在控制台输出一个字符串格式的key-value数据,如果此cookie的属性是httponly=true就不能通过此方法获取。

三、会话跟踪技术--session

1、对session的理解

session把数据存放在服务器上,并使用一个标签session-key唯一标记此数据。session-key作为cookie发送给客户端,即客户端只保存session-key,然后通过cookie发送给服务端,以表明身份,所以session比cookie安全。

每一次请求到达服务器的时候,服务器获取cookie中保存的session-key,并在数据库django-session表中寻找对应的session-data,进一步处理业务逻辑。

session的使用有如下优点:
1、数据保存在服务端,客户端仅保存一个senssionid
 2、sessionid数据量很小,适合每次发送
3、安全性,sessionid是一个随机字符串,不携带任何私密数据

2、session的使用接口

session的设置

django实现了session,帮我们完成了很多操作,且提供使用的接口非常简单:

request.session['name'] = 'xxx'

设置session的时候会执行如下三个操作:
1、创建一个随机字符串作为sessionid
2、把sessionid作为session-key,以及一个session_data字典加入到django-session表中
3、set-cookie,把sessionid发送给客户端

注意1:从底层源码来看,session_data其实就是一个字典{},然后通过orm存到django_session表中(应该有dict-->str的序列化和加密操作)

注意2:如果发现客户端的cookie中含有seesionid说明不是第一次登录,将会使用此sessionid并更新此sessionid对应的session_data数据

注意3:如果有两个用户在同一台电脑的同一个浏览器上,访问同一个url,因为sessionid是作为cookie存在,所以两个人会使用同一个sessionid。

而对于服务器而言,只认sessionid不认人,使用同一个sessionid的操作会覆盖之前的数据以导致在服务端上的session_data数据会相互覆盖,这样的结果是数据紊乱(尤其当两人的数据项目数量不一致时更严重)

session的读取

读取session的接口同样很简单:

name = request.session['name']

读取的时候会执行如下三个操作:
1、获取request.COOKIES中的sessionid
2、拿着sessionid作为session_key到数据库的django-session表中查找对应的session-data,底层就是执行orm的objects.filter(session_key=sessionid)
3、获取session-data中的数据并进一步处理

session的删除

删除session的接口:
1、del request.session[xxx]   # 删除一个会话数据属性
2、request.session.flush()    # 删除所有会话数据

清空会话信息时会执行如下操作:
1、删除django-session表中的session-key=sessionid的记录,底层操作就是执行orm的objects.filter(session_key=sessionid).delete()
2、删除response中的cookie里的sessionid记录

注意1:服务器把sessionid作为cookie的数据发给客户端保存,一般是会话cookie即不关闭浏览器程序就可以一直保持会话跟踪。但一旦客户端关闭了浏览器,则此sessionid便不再有效。但django颁发的cookie默认有效时间是2周,所以cookie会被保存到客户端硬盘上,即使关闭了浏览器也继续保存。

注意2:因为服务器无法获知客户端浏览器将会在什么时候关闭,更无法获知浏览器什么时候会执行清空cookie的操作。客户端一般只有在logout的时候才会主动告知删除session,其他情况下浏览器不会主动告知,所以服务器的session不能无限保存,被迫要设置失效时间(不然存储空间浪费),在一定时间内如果还没有用户重新访问此session,便被服务端认为此用户已失效,进而可以删除session数据。

3、session的属性

settings中还可以配置全局的session属性:

# 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,默认修改之后才保存(默认)

4、使用session的问题

1、session的正常工作依赖于cookie的启用,如果客户端禁用cookie功能,该如何保证session正常工作?---重写URL

2、同一台电脑同一个浏览器,访问同一个url,保存着同一个sessionid,如何处理多用户使用同一sessionid登录而导致的数据紊乱问题?---使用用户认证组件,使用账户密码来区别用户

四、总结

1、cookie和session都是为了解决http协议自身并不支持状态维持的缺点。
2、会话跟踪的目的是为了让多次请求之间可以共享数据,以提供更好的用户体验。
3、cookie和session都需要保存状态维持数据,只不过cookie是保存在客户端,session是保存在服务端。
4、分析和研究两者的技术相同点和区别有助于加深对会话跟踪的理解和使用。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python中使用异常处理来判断运行的操作系统平台方法
Jan 22 Python
python文件名和文件路径操作实例
Sep 29 Python
python中kmeans聚类实现代码
Feb 23 Python
python pickle存储、读取大数据量列表、字典数据的方法
Jul 07 Python
python双向链表原理与实现方法详解
Dec 03 Python
tensorflow之自定义神经网络层实例
Feb 07 Python
Python库skimage绘制二值图像代码实例
Apr 10 Python
结束运行python的方法
Jun 16 Python
如何在python中判断变量的类型
Jul 29 Python
详解Python Celery和RabbitMQ实战教程
Jan 20 Python
Pytorch - TORCH.NN.INIT 参数初始化的操作
Feb 27 Python
pygame面向对象的飞行小鸟实现(Flappy bird)
Apr 01 Python
Python访问MongoDB,并且转换成Dataframe的方法
Oct 15 #Python
Django框架的中的setting.py文件说明详解
Oct 15 #Python
python得到电脑的开机时间方法
Oct 15 #Python
python得到单词模式的示例
Oct 15 #Python
详解python如何在django中为用户模型添加自定义权限
Oct 15 #Python
Python 实现某个功能每隔一段时间被执行一次的功能方法
Oct 14 #Python
Python 实现异步调用函数的示例讲解
Oct 14 #Python
You might like
php cookie 作用范围?不要在当前页面使用你的cookie
2009/03/24 PHP
有关JSON以及JSON在PHP中的应用
2010/04/09 PHP
php操作xml入门之xml基本介绍及xml标签元素
2015/01/23 PHP
php单文件版在线代码编辑器
2015/03/12 PHP
thinkPHP模型初始化实例分析
2015/12/03 PHP
thinkphp3.x中display方法及show方法的用法实例
2016/05/19 PHP
PHP+Apache实现二级域名之间共享cookie的方法
2019/07/24 PHP
Yii Framework框架开发微信公众平台示例
2020/04/26 PHP
jquery ajax请求方式与提示用户正在处理请稍等
2014/09/01 Javascript
Jquery实现由下向上展开效果的例子
2014/12/08 Javascript
基于jquery实现一个滚动的分步注册向导-附源码
2015/08/26 Javascript
基于jQuery实现表格内容的筛选功能
2016/08/21 Javascript
利用js+css+html实现固定table的列头不动
2016/12/08 Javascript
Javascript中click与blur事件的顺序详析
2017/04/25 Javascript
浅谈用Webpack路径压缩图片上传尺寸获取的问题
2018/02/22 Javascript
基于jQuery实现的设置文本区域的光标位置
2018/06/15 jQuery
js中对象与对象创建方法的各种方法
2019/02/27 Javascript
C#程序员入门学习微信小程序的笔记
2019/03/05 Javascript
基于JavaScript实现留言板功能
2020/03/16 Javascript
vue实现移动端项目多行文本溢出省略
2020/07/29 Javascript
Python计算时间间隔(精确到微妙)的代码实例
2019/02/26 Python
python实现二级登陆菜单及安装过程
2019/06/21 Python
python爬虫 Pyppeteer使用方法解析
2019/09/28 Python
详解Python3迁移接口变化采坑记
2019/10/11 Python
Python3 Tkinkter + SQLite实现登录和注册界面
2019/11/19 Python
python中前缀运算符 *和 **的用法示例详解
2020/05/28 Python
CSS3改变浏览器滚动条样式
2019/01/04 HTML / CSS
css3翻牌翻数字的示例代码
2020/02/07 HTML / CSS
波兰品牌鞋履在线商店:Eastend.pl
2020/01/11 全球购物
小学运动会表扬稿
2014/01/19 职场文书
公务员综合考察材料
2014/02/01 职场文书
导师评语大全
2014/04/26 职场文书
公司任命书范本
2014/06/04 职场文书
2015大学党建带团建工作总结
2015/07/23 职场文书
2019班干部竞选演讲稿范本!
2019/07/08 职场文书
Python FuzzyWuzzy实现模糊匹配
2022/04/28 Python