Session和Cookie

浏览器端和服务器端身份认证的一种方式。简单讲,就是为了让服务端确定你是谁。

无状态,无连接

  • 无连接:Http1.1之前,都是一个请求一个连接,连接用完即刻断开,其实是无连接。
    • 有连接:是因为他基于TCP协议,是面向对象的,需要3次握手、4次断开
    • 短连接:而tcp的连接创建销毁成本高,对服务器有很大影响。所以,自http1.1开始,支持keep-alive,默认页开启,一个连接打开后,会保持一段时间(可以设置),浏览器再访问该服务器就使用这个TCP连接,减轻了服务器压力,提高了效率
  • 无状态:服务器端没有记录每一次客户端请求相关的任何状态数据,服务器无法确定2次请求之间的联系,即使是前后2次同一个浏览器也没有任何数据能够判断出是同一个浏览器的请求,后来可以通过cookie、session来判断

cookie技术

  • 键值对信息
  • 是一种客户端、服务器端传递数据的技术
  • 一般来说cookie信息是在服务器端生成,返回给浏览器端的
  • 浏览器端可以保持这些值,浏览器对同一域发起每一请求时,都会把cookie信息发送给服务器端
  • 服务端收到浏览器端发过来的cookie,处理这些信息,可以用来判断这次请求是否和之前的请求有关联。

曾经Cookie唯一在浏览器端存储数据的手段,目前浏览器端存储数据的方案很多,Cookie正在被淘汰。

当服务器收到HTTP请求时,服务器可以在响应头里面添加一个Set-Cookie键值对。浏览器收到响应后通常会保存这些Cookie,之后对该服务器每一次HTTP请求中,都通过Cookie请求头部将Cookie信息发送给服务器。

另外,Cookie的过期时间、域、路径、有效期、适用站点都可以根据需要来指定。

可以使用 Set-Cookie: NAME=VALUE;Expires=DATE;Path=PATH;Domain=DOMAIN_NAME;SECURE

例如:

Text
Set-Cookie:aliyungf_tc=AQAAAJDwJ3Bu8gkAHbrHb4zlNZGw4Y; Path=/; HttpOnly set-cookie:test_cookie=CheckForPermission; expires=Tue, 19-Mar-2018 15:53:02 GMT; path=/; domain=.doubleclick.net Set-Cookie: BD_HOME=1; path=/
key value说明
Cookie过期 Cookie可以设置过期终止时间,过期后将被浏览器清除。
如果缺省,Cookie不会持久化,浏览器关闭Cookie消失,称为会话级cookie
Cookie域 域确定有哪些域可以存取这个Cookie
缺省设置属性值为当前主机,例如www.dujie.com
如果设置为dujie.com表示包括子域
Path 确定哪些目录及子目录访问可以使用该Cookie
Secure 表示Cookie随着HTTPS加密过的请求发送给服务端
有些浏览器已经不允许http://协议使用Secure了
这个Secure不能保证Cookie是安全的,Cookie中不要传输敏感信息
HttpOnly 将Cookie设置此标记,就不能被JavaScript访问,只能发送给服务端
Text
Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT; Secure; HttpOnly 告诉浏览器端设置这个Cookie的键值对,有过期时间,使用HTTPS加密传输到服务器端,且不能被浏览器中JS脚本访问该Cookie
Text
Cookie的作用域:Domain和Path定义Cookie的作用域 Domain domain=www.magedu.com 表示只有该域的URL才能使用 domain=magedu.com 表示可以包含子域,例如www.magedu.com、python.magedu.com等 Path path=/ 所有/的子路径可以使用 domain=www.magedu.com; path=/webapp 表示只有www.magedu.com/webapp下的URL匹配,例 如http://www.magedu.com/webapp/a.html就可以

缺点

  • Cookie一般明文传输(Secure是加密传输),安全性极差,不要传输敏感数据
  • 一个域的条目数不易太多,单条有4kB大小限制
  • 每次请求中都会发送Cookie,增加了流量
其他持久化技术

LocalStorage

  • 浏览器端持久化方案之一,HTML5标准增加的技术
  • 依然采用键值对存储数据
  • 数据会存储在不同的域名下面
  • 不同浏览器对单个域名下存储数据的长度支持不同,有的最多支持2MB。

https://developer.mozilla.org/zh-CN/docs/Web/API/Window/localStorage

SessionStorage和LocalStorage差不多,它是会话级的,浏览器关闭,会话结束,数据清除。

IndexedDB

  • 一个域一个datatable
  • key-valuede检索方式
  • 建立在关系型的数据模型之上,具有索引表、游标、事务等概念

Session技术

浏览器第一次请求时,服务端会返回给浏览器一个sessionid,浏览器会把sessionid保存,下次在请求的时候,在请求头的cookie中会携带此sessionid,服务器端收到该请求后,会判断内存或数据库中是否有此sessionid,如果有则直接返回

Web服务端,尤其是动态网页服务端Server,有时需要知道浏览器放是谁?但是HTTP是无状态的,怎么办?

服务端会为每一次浏览器端第一次访问生成一个SessionID,用来唯一标识该浏览器,通过响应报文的Set-Cookie发送到浏览器端

Text
Set-Cookie:JSESSIONID=741248A52EEB83DF182009912A4ABD86.Tomcat1; Path=/; HttpOnly

浏览器端收到之后并不永久保存这个cookie,可以是会话级的。浏览器访问服务端时,会使用与请求域相关的cookies,也会带上这个sessionID的cookie值。

动态网页技术,也需要知道用户身份,但是HTTP是无状态协议,无法知道。必须提出一种技术,让客户端提交的信息可以表明身份。只能是服务端发出一个凭证,即SessionID,让浏览器每次请求时发出Cookies的同时带上这个SessionID,且过期作废,浏览器还不能更改。这个技术为了给浏览器发凭证就使用了现在的Cookie技术。

服务端会维持主题歌SessionID一段时间,如果超时,会清理这些超时没有人访问的SessionID。如果浏览器发来的SessionID无法在服务端找到,就会自动再次分配新的SessionID,并通过set-Cookie发送到浏览器端以覆盖原有的存在浏览器中的会话级SessionID。

也就是说服务器端会为浏览器端在内存开辟空间保存SessionID,同时和这个SessionID关联存储更多键值对。这种为客户端在服务端维护相关状态数据的技术,就是Session技术。

推荐图书《HTTP权威指南》

Session开启后,会为浏览器端设置一个Cookie值,即SessionID。

这个SessionID的Cookie如果是会话级的,浏览器不做持久化存储只放在内存中,并且浏览器关闭自动清除。

浏览器端发起HTTP请求后,这个SessionID会通过Cookie发到服务器端,服务器端就可以通过这个ID查到对应的一个字典结构。如果查无此ID,就为此浏览器重新生成一个SessionID,为它建立一个SessionID和空字典的映射关系。

可以在这个SessionID关联的字典中,存入键值对来保持与当前会话相关的更多信息

  • Session会定期过期清除
  • Session占用服务器端内存
  • Session如果没有持久化,如果服务程序崩溃,那么所有Session信息丢失
  • Session可以持久化到数据库中,如果服务程序崩溃,那么可以从数据库中恢复

开启Session支持

Django可以使用Session

  • 在settings中,MIDDLEWARE设置中,启用’django.contrib.sessions.middleware.SessionMiddleware’
  • INSTALLED_APPS设置中,启用’django.contrib.sessions’。它是基于数据库存储的Session
  • Session不使用,可以关闭上述配置,以减少开销
  • 在数据库的表中的django_session表,记录session信息。但可以使用文件系统或其他cache来存储
session清除

登录成功,为当前session在django_session表中增加一条记录,如果没有显式调用logout() 函数或request.session.flush(),那么该记录不会消失。Django也没有自动清除失效记录的功能。

request.session.flush()会清除当前session,同时删除表记录

但Django提供了一个命令clearsessions,建议放在cron中定期执行。

Text
$ django-admin.py clearsessions $ manage.py clearsessions
Text
from django.http import HttpRequest, HttpResponse def test_index(request:HttpRequest):    '''cookie和session测试'''    print('~' * 30)    print(request.session.get('abc'))    res = HttpResponse('test')    res.cookies['tttt'] = 'vvvvvv'    print(request.session.keys()) # SessionStore    import random    request.session['abc'] = str(random.randint(100, 200))    print('~' * 30)    return res
Text
from django.contrib.sessions.models import Session # 使用sessionid查询数据库中session相关的数据 s = Session.objects.get(pk='m600uyia87y0imcn6ghwfv79hgotyf4r') print(s.expire_date) print(s.session_data)  # 序列化后的数据 print(s.get_decoded())

测试:

在view中定义

from django.shortcuts import render
from django.views import View
import  django
from django.core.wsgi import get_wsgi_application
from django.http.request import HttpRequest
from django.http.response import HttpResponse,JsonResponse



def t1(request:HttpRequest):
    print(request.COOKIES)
    res = HttpResponse('t1 result')
    res.cookies['trttttttt'] = 'vvvvvvvv'
    request.session['cart'] = [1,2,3]
    return res