cookie、session、token
一、cookie
1、cookie的由来
- 会话跟踪
大家都知道HTTP协议是无状态的。
无状态的意思是每次请求都是独立的,它的执行情况和结果与前面的请求和之后的请求都无直接关系,它不会受前面的请求响应情况直接影响,也不会直接影响后面的请求响应情况。
对服务器来说,每次的请求都是全新的。
状态可以理解为客户端和服务器在某次会话中产生的数据,那无状态的就以为这些数据不会被保留。会话中产生的数据又是我们需要保存的,也就是说要“保持状态”。因此Cookie就是在这样一个场景下诞生。
HTTP协议中可以使用Cookie来完成会话跟踪;
在web开发中,使用session来完成会话跟踪,session底层依赖Cookie技术
2、cookie是什么?
# 简单来说,cookie就是浏览器上的键值对,类似于python中的字典
具体指的是一段小信息,它是随着服务器端的响应发送给客户端浏览器,存储在浏览器上的一组组键值对,下次访问服务器时,浏览器会自动携带这些键值对,以便服务器提取有用的信息
3、cookie的原理
由服务器产生内容,浏览器收到请求后保存在本地;
当浏览器再次访问时,浏览器会自动带上cookie,这样服务器就能通过cookie的内容来判断这个是谁了
4、Cookie规范
HTTP的Cookie规范:
- Cookie大小上限为4KB
- 一个服务器最多在客户端浏览器上保存20个cookie
- 一个浏览器最多保存300个Cookie
但是不绝对,有些浏览器会对其做扩展
不同的浏览器之间不共享Cookie
服务器端发送重复的Cookie会覆盖原有的Cookie
4、django中操作cookie(增删改查)
- 获取cookie
request.COOKIES['key']
request.get_signed_cookie(key, default=PAISE_ERROR, salt='', max_age=None)
# 参数:
- default:默认值
- salt:加密盐
- max_age:后台控制的过期时间
- 设置Cookie(增、改)
obj = HttpResponse(...)
obj.set_cookie(key, value,...)
obj.set_signed_cookie(key, value,salt='加密盐', max_age = None,...)
# 参数:
- key:键
- value:值
- max_age 超时时间
- expires=None, 超时时间(IE requires expires, so set it if hasn't been already)
- path : Cookie生效的路径,/表示根路径,特殊的:跟路径的cookie可以被任何url的页面访问
- domain : Cookie生效域名
- secure = False :https传输
- httponly = False 只能http协议传输,无法被JavaScript获取,(不是绝对,底层抓包也能获取到也可以被覆盖)
- 删除Cookie (本质上不是删除,是设置浏览器上的cookie过期)
def del_cookie(request):
obj = HttpResponse('删掉了name')
obj.delete_cookie('name')
return obj
5、带签名的cookie(加盐、加密)
- 增:obj.set_signed_cookie('name','cc','123')
- 删:ojb.delete_cookie('name')
- 查:request.get_signed_cookie('name',salt='123')
- 改:obj.set_signed_cookie('name', 'xxx', '123')
二、Session
1、Session的由来
Cookie虽然在一定程度上解决了“保持状态”的需求,但是由于Cookie本身最大支持4096字节,以及Cookie本身保存在客户端,可能被拦截或窃取,因此就需要有一种新的东西,它能支持更多的字节,并且他保存在服务器,有较高的安全性。这就是Session。
总结而言:Cookie弥补了HTTP无状态的不足,让服务器知道来的人是“谁”;但是Cookie以文本的形式保存在本地,自身安全性较差;所以我们就通过Cookie识别不同的用户,对应的在Session里保存私密的信息以及超过4096字节的文本。
另外,上述所说的Cookie和Session其实是共通性的东西,不限于语言和框架。
![session的由来](https://gitee.com/cuicheng688/img/raw/master/img/20201119202152.png)
2、django中session的使用
1、session是保存在于服务端的键值对
2、同一个浏览器不允许登录多个账户,不同浏览器可以登录同一个账户
3、session的使用:(前提必须迁移数据库)
-增:request.session['name'] = 'cc'
-查:request.session['name']
-改:request.session['name'] = 'xxx'
-删:del request.seesion['name']
-设置过期时间:request.session.set_expiry(value) # 单位是秒
* 如果value是个整数,如60*60*24*5,那么在value个秒后,session失效
* 如果value是个datetime或者timedelta,那么session会在这个指定的时间后失效
* 如果value是0,用户关闭浏览器session就会失效
* 如果value是None,session会依赖于全局session失效策略
4、session的其他使用:
- request.session.setdefault('k1',123)
- request.session.get('name', None)
- del request.session['k1']
- request.session.keys()
- request.session.values()
- request.session.items()
- request.session.session_key # 获取那个随机字符串,django_session表中的session_key字段
- request.session.clear_expired() # 清除过期的session(清除失效日期小于当前日期的数据)
- request.session.exists('session_key') # 判断这个随机字符串(session_key字段)中有没有数据
- request.session.delete() # 删除所有的值,在django_session表中删除当前登录者的整条记录(只删除数据库中的)
- request.session.flush() # 删除django_session中的记录,并把cookie设置成过期(即数据库和cookie都删)
![image-20201022153030955](https://gitee.com/cuicheng688/img/raw/master/img/image-20201022153030955.png)
![dd](https://gitee.com/cuicheng688/img/raw/master/img/dd.png)
3、django中session的配置
def set_cookie(self, key, value='', max_age=None, expires=None, path='/',
domain=None, secure=False, httponly=False)
# 参数详解:
- key
- value
- max_age:过期时间,有默认值,(如果传值的话,要传数字,单位是秒)
- expires:传时间对象,如:datetime.timedelta(days=5),表示5天后过期
- path: 默认为/,表示当前域下所有的路径
- domain:表示在哪个域下有效
- secure: 是否https传输cookie
- httponly:cookie只支持http传输
1、数据库Session
SESSION_ENGINE = 'django.contrib.sessions.backends.db' # 引擎(默认)
2. 缓存Session
SESSION_ENGINE = 'django.contrib.sessions.backends.cache' # 引擎
SESSION_CACHE_ALIAS = 'default' # 使用的缓存别名(默认内存缓存,也可以是memcache),此处别名依赖缓存的设置
3. 文件Session
SESSION_ENGINE = 'django.contrib.sessions.backends.file' # 引擎
SESSION_FILE_PATH = None # 缓存文件路径,如果为None,则使用tempfile模块获取一个临时地址tempfile.gettempdir()
4. 缓存+数据库
SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db' # 引擎
5. 加密Cookie Session
SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies' # 引擎
其他公用设置项:
SESSION_COOKIE_AGE = 1209600 # Session的cookie失效日期(2周)(默认)***记住
---了解---
SESSION_EXPIRE_AT_BROWSER_CLOSE = False # 是否关闭浏览器使得Session过期(默认)
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_SAVE_EVERY_REQUEST = False # 是否每次请求都保存Session,默认修改之后才保存(默认)
示例:
# 设置session
# django框架默认,把session信息存到数据库中了,django_session表
# 先迁移数据库
def session_set(request):
# request.session是个字典
# 写了下面那一句话,干了如下几件事
'''
# 一个浏览器,一个随机字符串
1 生成一个随机字符串asdfasdf,把随机字符串和name=lqz数据加密存到django_session表中
2 会把这个随机字符串放到cookie中
obj.set_cookie('sessionid',asdfasdf)
'''
request.session['name'] = 'cc'
request.session['age'] = 20
return HttpResponse('session写入了name和age')
def session_set2(request):
request.session['name'] = 'jack'
request.session['sex'] = 'male'
return HttpResponse('session重设了name,新增了sex')
三、CBV中加装饰器
outer是个登录验证装饰器
- 方式一:(加在类上)
from django.views import View
from django.utils.decorators import method_decorator
@method_decorator(outer, name='get')
@method_decorator(outer, name='post')
class UserInfo(View):
def get(self, request, *args, **kwargs):
return HttpResponse('ok')
def post(self, request, *args, **kwargs):
return HttpResponse('ok')
- 方式二(加在方法上)
from django.views import View
from django.utils.decorators import method_decorator
class UserInfo(View):
@method_decorator(outer)
def get(self, request, *args, **kwargs):
return HttpResponse('ok')
@method_decorator(outer)
def post(self, request, *args, **kwargs):
return HttpResponse('ok')