当前位置:   article > 正文

对Django中的cookie与session详解和理解_如果设置session = 30 cookie 的max-age有什么用

如果设置session = 30 cookie 的max-age有什么用

cookie与session的实现原理

在这里插入图片描述
HTTP被设计为”无状态”,每次请求都处于相同的空间中。 在一次请求和下一次请求之间没有任何状态保持,我们无法根据请求的任何方面(IP地址,用户代理等)来识别来自同一人的连续请求。

对于HTTP的无状态性的原因,相关RFC里并没有解释,但联系到HTTP的历史以及应用场景,我们可以推测出一些理由:

  1. 设计HTTP最初的目的是为了提供一种发布和接收HTML页面的方法。那个时候没有动态页面技术,只有纯粹的静态HTML页面,因此根本不需要协议能保持状态;
  2. 用户在收到响应时,往往要花一些时间来阅读页面,因此如果保持客户端和服务端之间的连接,那么这个连接在大多数的时间里都将是空闲的,这是一种资源的无端浪费。所以HTTP原始的设计是默认短连接,即客户端和服务端完成一次请求和响应之后就断开TCP连接,服务器因此无法预知客户端的下一个动作,它甚至都不知道这个用户会不会再次访问,因此让HTTP协议来维护用户的访问状态也全然没有必要;
  3. 将一部分复杂性转嫁到以HTTP协议为基础的技术之上可以使得HTTP在协议这个层面上显得相对简单,而这种简单也赋予了HTTP更强的扩展能力。事实上,session技术从本质上来讲也是对HTTP协议的一种扩展。
    总而言之,HTTP的无状态是由其历史使命而决定的。但随着网络技术的蓬勃发展,人们再也不满足于死板乏味的静态HTML,他们希望web应用能动起来,于是客户端出现了脚本和DOM技术,HTML里增加了表单,而服务端出现了CGI等等动态技术。

上图很明显的展示了Django的session与cookie的实现原理。服务器会生成两份相同的cookie字符串(键值对),一份保存在本地,一份发向请求的浏览器。浏览器将收到的cookie字符串保存下来,当下次再发请求时,会将信息与这段cookie一同发送到服务器,服务器得到这段cookie会与本地保存的那份判断是否相同,如果相同就表示用户已经登录成功,保存用户登录成功的状态。

Django的session保存在数据库中的数据相当于一个大字典,key为cookie的字符串,value仍是一个字典,字典的key和value为用户设置的相关信息。这样就可以方便的存取session里面的信息。

cookie详解

1.cookie的定义
cookie 由服务器生成,保存在浏览器中,cookie就是一系列的键值对 key=value构成字符串,键值对之间由一个分号和一个空格隔开。
在这里插入图片描述

2.cookie的作用:
登录状态的判定

3.cookie 的特点:

  • 以键值对的方式进行存储。
  • 通过浏览器访问一个网站的时候,会将浏览器存储的相关网站的所有的cookie 都发送给该网站的服务器。 获取的时候使用 request.COOKIES 来获取
  • cookie 是基于域名安全的, www.baidu.com ,www.ujiuye.com
  • cookie 是有过期时间的,如果不指定时间,默认关闭浏览器则失效。
    设置时间: max_age 单位是秒(s)

cookie的工作原理
每个客户端最多保持三百个cookie,每个域名下最多20个Cookie(实际上一般浏览器现在都比这个多,如Firefox是50个),而每个cookie的大小为最多4K,不过不同的浏览器都有各自的实现。对于cookie的使用,最重要的就是要控制cookie的大小,不要放入无用的信息,也不要放入过多信息。

cookie的值是 如何传递的?

无论使用何种服务端技术,只要发送回的HTTP响应中包含如下形式的头,则视为服务器要求设置一个cookie:Set-cookie:name=name;expires=date;path=path;domain=domain

支持cookie的浏览器都会对此作出反应,即创建cookie文件并保存(也可能是内存cookie),用户以后在每次发出请求时,浏览器都要判断当前所有的cookie中有没有没失效(根据expires属性判断)并且匹配了path属性的cookie信息,如果有的话,会以下面的形式加入到请求头中发回服务端:Cookie: name="zj"; Path="/linkage"

服务端的动态脚本会对其进行分析,并做出相应的处理,当然也可以选择直接忽略。

请求参数:
在这里插入图片描述
请求的头中Cookie就是把所有的服务器之前返回的Cookie以分号;进行分割,拼成了一个字符串传给了服务器。

响应参数:
在这里插入图片描述
返回数据的头中有一系列的key为Set-Cookie的键值对

第一个Set-Cookie:JSESSIONID
这时用来实现会话的,如果是第一次访问,请求的参数中没有这个参数,服务器会生成一个JSESSIONID放在响应头中,下次在访问的时候,浏览器就会把这个参数带上 。

第一幅图中的Cookie中就有JSESSIONID,这说明已经不是第一次访问了
而第二幅图中返回的头中有JSESSIONID,说明这次的请求是第一次请求
这两幅图并不是同一次的请求和响应

第二个Set-Cookie
都是服务器返回的其它键值对,浏览器不用关心它们是什么意思,下次访问的时候直接在返回给服务端就是。
其中第二个Set-Cookie长得与其它不太一样,多了一个Expires,这个是表示这个键值对过期时间,如果过期了,下次请求浏览器就不会把这个键值对带过去

cookie 的属性选项

每个cookie都有一定的属性,如什么时候失效,要发送到哪个域名,哪个路径等等。这些属性是通过cookie选项来设置的,cookie选项包括:expires、domain、path、secure、HttpOnly。

在设置任一个cookie时都可以设置相关的这些属性,当然也可以不设置,这时会使用这些属性的默认值。在设置这些属性时,属性之间由一个分号和一个空格隔开。代码示例如下:

"key=name; expires=Thu, 25 Feb 2016 04:18:00 GMT; domain=ppsc.sankuai.com; path=/; secure; HttpOnly"

  • 1
  • 2
  • expires
    expires选项用来设置“cookie 什么时间内有效”。expires其实是cookie失效日期,expires必须是 GMT 格式的时间(可以通过new Date().toGMTString()或者 new Date().toUTCString() 来获得)。

    如expires=Thu, 25 Feb 2016 04:18:00 GMT表示cookie讲在2016年2月25日4:18分之后失效,对于失效的cookie浏览器会清空。如果没有设置该选项,则默认有效期为session,即会话cookie。这种cookie在浏览器关闭后就没有了。

    expires 是 http/1.0协议中的选项,在新的http/1.1协议中expires已经由 max-age 选项代替,两者的作用都是限制cookie 的有效时间。expires的值是一个时间点(cookie失效时刻= expires),而max-age 的值是一个以秒为单位时间段(cookie失效时刻= 创建时刻+ max-age)。

    另外,max-age 的默认值是 -1(即有效期为 session );若max-age有三种可能值:负数、0、正数。负数:有效期session;0:删除cookie;正数:有效期为创建时刻+ max-age

  • domainpath

    domain表示的是cookie所在的域,默认为请求的地址,如网址为
    www.test.com/test/test.aspx, 那么domain默认为www.test.com

path表示cookie所在的目录,asp.net默认为/,就是根目录。在同一个服务器上有目录如下:/test/,/test/cd/,/test/dd/,现设一个cookie1的path为/test/,cookie2的path为/test/cd/,那么test下的所有页面都可以访问到cookie1,而/test/和/test/dd/的子页面不能访问cookie2。这是因为cookie能让其path路径下的页面访问。

两者加起来就构成了 URL,domain和path一起来限制 cookie 能被哪些 URL 访问。

一句话概括:某cookie的 domain为“baidu.com”, path为“/ ”,若请求的URL(URL 可以是js/html/img/css资源请求,但不包括 XHR 请求)的域名是“baidu.com”或其子域如“api.baidu.com”、“dev.api.baidu.com”,且 URL 的路径是“/ ”或子路径“/home”、“/home/login”,则浏览器会将此 cookie 添加到该请求的 cookie 头部中。

所以domain和path2个选项共同决定了cookie何时被浏览器自动添加到请求头部中发送出去。如果没有设置这两个选项,则会使用默认值。domain的默认值为设置该cookie的网页所在的域名,path默认值为设置该cookie的网页所在的目录。

特别说明1:
发生跨域xhr请求时,即使请求URL的域名和路径都满足 cookie 的 domain 和 path,默认情况下cookie也不会自动被添加到请求头部中。

特别说明2:
domain是可以设置为页面本身的域名(本域),或页面本身域名的父域,但不能是公共后缀 public suffix。举例说明下:如果页面域名为 www.baidu.com, domain可以设置为“www.baidu.com”,也可以设置为“baidu.com”,但不能设置为“.com”或“com”。

  • secure
    secure选项用来设置cookie只在确保安全的请求中才会发送。当请求是HTTPS或者其他安全协议时,包含 secure 选项的 cookie才能被发送至服务器。

    默认情况下,cookie不会带secure选项(即为空)。所以默认情况下,不管是HTTPS协议还是HTTP协议的请求,cookie 都会被发送至服务端。但要注意一点,secure选项只是限定了在安全情况下才可以传输给服务端,但并不代表你不能看到这个 cookie。

设置cookie

from django.shortcuts import render, HttpResponse

# 设置cookie
def set_cookie(request):
    response = HttpResponse('设置cookie')
    # 设置cookie
    response.set_cookie('num', 10, max_age=3600 * 24 * 14)
    return response


# 读取cookie
def get_cookie(request):
    # 通过 键 获取值
    num = request.COOKIES['num']
    return HttpResponse(num)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
from django.utils.datastructures import MultiValueDictKeyError

# 记住用户名
def login(request):
    if request.method == 'POST':
        username = request.POST.get('username')
        pwd = request.POST.get('pwd')
        # remember = request.POST['remember']
        try:
            remember = request.POST['remember']
        except MultiValueDictKeyError as e:
            remember = 'xxx'
            # print(remember)  # 不勾选 返回None 选中返回on
        if username == 'zs' and pwd == '123':
            # 1. 如果选中,就设置 cookie
            print(remember)  # 不勾选 返回None 选中返回on
            if remember == 'on':
                response = HttpResponse('登录成功...')
                response.set_cookie('username', username, max_age=3600 * 24 * 14)
                return response
    # 获取cookie的值,第一次get 请求 是没有设置cookie的因此 返回默认值 ''
    username = request.COOKIES.get('username', '')  # None

    return render(request, 'app01/login.html', {'username': username})

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

session详解

session定义
Session一般译作会话,牛津词典对其的解释是进行某活动连续的一段时间。从不同的层面看待session,它有着类似但不全然相同的含义。比如,在web应用的用户看来,他打开浏览器访问一个电子商务网站,登录、并完成购物直到关闭浏览器,这是一个会话。而在web应用的开发者开来,用户登录时我需要创建一个数据结构以存储用户的登录信息,这个结构也叫做session。

因此在谈论session的时候要注意上下文环境。而本文谈论的是一种基于HTTP协议的用以增强web应用能力的机制或者说一种方案,它不是单指某种特定的动态页面技术,而这种能力就是保持状态,也可以称作保持会话。

创建session可以概括为三个步骤

  1. 生成全局唯一标识符(sessionid);
  2. 开辟数据存储空间。一般会在内存中创建相应的数据结构,但这种情况下,系统一旦掉电,所有的会话数据就会丢失,如果是电子商务网站,这种事故会造成严重的后果。不过也可以写到文件里甚至存储在数据库中,这样虽然会增加I/O开销,但session可以实现某种程度的持久化,而且更有利于session的共享;
  3. 将session的全局唯一标示符发送给客户端
    问题的关键就在服务端如何发送这个session的唯一标识上。联系到HTTP协议,数据无非可以放到请求行、头域或Body里,基于此,一般来说会有两种常用的方式:cookieURL重写
  • cookie:服务端只要设置Set-cookie头就可以将session的标识符传送到客户端,而客户端此后的每一次请求都会带上这个标识符,由于cookie可以设置失效时间,所以一般包含session信息的cookie会设置失效时间为0,即浏览器进程有效时间。至于浏览器怎么处理这个0,每个浏览器都有自己的方案,但差别都不会太大(一般体现在新建浏览器窗口的时候);

  • URL重写:
    所谓URL重写,顾名思义就是重写URL。试想,在返回用户请求的页面之前,将页面内所有的URL后面全部以get参数的方式加上session标识符(或者加在path info部分等等),这样用户在收到响应之后,无论点击哪个链接或提交表单,都会在再带上session的标识符,从而就实现了会话的保持。读者可能会觉得这种做法比较麻烦,确实是这样,但是,如果客户端禁用了cookie的话,URL重写将会是首选。

def set_session(request):
    # 设置session
    request.session['username'] = 'zs'
    request.session['age'] = 18
    # request.session.set_expiry(2)  # 2s后过期
    # 默认是14天后过期, 0 表示关闭浏览器过期
    # 5s 表示 5s后过期
    return HttpResponse('设置session')


def get_session(request):
    """获取session"""
    username = request.session['username']
    age = request.session['age']
    return HttpResponse(username + ":" + str(age))


# 删除session
def clear_session(request):
    request.session.flush()  # 将整条记录删除
    request.session.clear() # 删除内容部分
    # 删除指定的key
    del request.session['username']
    return HttpResponse('清除成功')

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/559485
推荐阅读
相关标签
  

闽ICP备14008679号