Session和Cookie
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
例如:
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访问,只能发送给服务端 |
Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT; Secure; HttpOnly
告诉浏览器端设置这个Cookie的键值对,有过期时间,使用HTTPS加密传输到服务器端,且不能被浏览器中JS脚本访问该Cookie
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发送到浏览器端
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中定期执行。
$ django-admin.py clearsessions
$ manage.py clearsessions
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
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