大家都知道HTTP协议是无状态的。
无状态的意思是每次请求都是独立的,它的执行情况和结果与前面的请求和之后的请求都无直接关系,它不会受前面的请求响应情况直接影响,也不会直接影响后面的请求响应情况。
一句有意思的话来描述就是人生只如初见,对服务器来说,每次的请求都是全新的。
随着交互式Web应用的兴起, 像在线购物网站,需要登录的网站等,马上面临一个问题,就是要管理会话,记住哪些人登录过系统,哪些人往自己的购物车中放商品,也就是说我必须把每个人区分开。会话中产生的数据又是我们需要保存的,也就是说要“保持状态”。因此Cookie就是在这样一个场景下诞生。
cookie是浏览器保存在用户电脑上的一小段文本,通俗的来讲就是当一个用户通过 http访问到服务器时,服务器会将一些 Key/Value键值对返回给客户端浏览器,并给这些数据加上一些限制条件,在条件符合时这个用户下次访问这个服务器时,数据通过请求头又被完整地给带回服务器,服务器根据这些信息来判断不同的用户。
cookie存储在客户端,也就是浏览器上,一般会限制cookie的个数为20个,并且单个cookie的大小不能超过4kb而且是明文存储不安全
先得到HttpResponse对象再进行设置
-
方法:response.set_cookie()
-
参数如下:
参数 说明 key cookie的key value cookie的值,设置 Cookie key相对应的值,都必须是字符串类型。如果值为 Unicode 字符,需要为字符编码。 如果值为二进制数据,则需要使用 BASE64 编码。 domain 指定 cookie 所属域名 path 指定 cookie 在哪个路径(路由)下生效,默认是 '/'。 如果设置为 /abc
,则只有/abc
下的路由可以访问到该 cookie,如:/abc/read
。max_age cookie 失效的时间,单位秒。如果为整数,则该 cookie 在 maxAge 秒后失效。如果为负数,该 cookie 为临时 cookie ,关闭浏览器即失效,浏览器也不会以任何形式保存该 cookie 。如果为 0,表示删除该 cookie 。默认为 -1。 - 比 expires 好用。 expires 过期时间,在设置的某个时间点后该 cookie 就会失效。 默认为1年 secure 该 cookie 是否仅被使用安全协议传输。安全协议有 HTTPS,SSL等,在网络上传输数据之前先将数据加密。默认为false。 当 secure 值为 true 时,cookie 在 HTTP 中是无效,在 HTTPS 中才有效。 httponly 如果给某个 cookie 设置了 httpOnly 属性,则无法通过 JS 脚本 读取到该 cookie 的信息,但还是能通过 Application 中手动修改 cookie,所以只是在一定程度上可以防止 XSS 攻击,不是绝对的安全
cookie 是不可跨域的: 每个 cookie 都会绑定单一的域名,无法在别的域名下获取使用,一级域名和二级域名之间是允许共享使用的(靠的是 domain)。
-
实例
路由
path('set_cookie/', test_cookie.set_cookie, name='set_cookie'), path('set_cookie_lifetime/', test_cookie.set_cookie_lifetime, name='set_cookie_lifetime'),
视图
# 设置cookie def set_cookie(req): res = HttpResponse('设置cookie') # 不设置过期时间 则为浏览会话结束时 res.set_cookie('name', 'lucky') return res
-
设置cookie并设置过期时间
def set_cookie_lifetime(req): res = HttpResponse('设置cookie并设置过期时间') # 设置过期时间为2分钟 res.set_cookie('name', 'lucky', max_age=120) return res
-
方法
request.COOKIES.get()
-
格式
req.COOKIES.get('key')
-
实例
路由
path('look_cookie/', test_cookie.look_cookie, name='look_cookie'),
视图
# 查看cookie def look_cookie(req): # 获取cookie 并设置默认值 res = req.COOKIES.get('name','default') return HttpResponse(res)
-
方法
delete_cookie()
-
格式
response.delete_cookie()
-
实例
路由
path('delete_cookie/', test_cookie.delete_cookie, name='delete_cookie'),
视图
def delete_cookie(req): res = HttpResponse('删除cookie') res.delete_cookie('name') return res
Cookie虽然在一定程度上解决了“保持状态”的需求,但是由于Cookie本身最大支持4096字节,以及Cookie本身保存在客户端,可能被拦截或窃取,因此就需要有一种新的东西,它能支持更多的字节,并且他保存在服务器,有较高的安全性。这就是Session。
问题来了,基于HTTP协议的无状态特征,服务器根本就不知道访问者是“谁”。那么上述的Cookie就起到桥接的作用。
我们可以给每个客户端的Cookie分配一个唯一的id,这样用户在访问时,通过Cookie,服务器就知道来的人是“谁”。然后我们再根据不同的Cookie的id,在服务器上保存一段时间的私密资料,如“账号密码”等等。
总结而言:Cookie弥补了HTTP无状态的不足,让服务器知道来的人是“谁”;但是Cookie以文本的形式保存在本地,自身安全性较差;所以我们就通过Cookie识别不同的用户,对应的在Session里保存私密的信息以及超过4096字节的文本。
另外,上述所说的Cookie和Session其实是共通性的东西,不限于语言和框架。
session的值存储于服务器端、数据库、内存、redis、文件中
将sessionid存储在cookie中,也就是当前数据的钥匙
django中 session默认的过期时间是14天
settings.py
INSTALLED_APPS = [
'django.contrib.sessions',
]
MIDDLEWARE = [
'django.contrib.sessions.middleware.SessionMiddleware',
]
session开启后,req才会有session属性
-
生成数据库表
python manage.py migrate
-
数据库配置
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'python36django', 'HOST':'127.0.0.1', 'PORT': 3306, 'PASSWORD': '123456', 'USER':'root', } }
-
安装pymysql
pip install pymysql
-
project/init.py
import pymysql pymysql.install_as_MySQLdb()
-
属性
req.session[key] = value
-
过期时间
req.session.set_expiry(value)
- 如果value是个整数,session会在些秒数后失效。
- 如果value是个datatime或timedelta,session就会在这个时间后失效。
- 如果value是0,用户关闭浏览器session就会失效。
- 如果value是None,session会依赖全局session失效策略。14天
-
实例
路由
path('set_session/', test_session.set_session, name='set_session'), path('set_session_lifetime/', test_session.set_session_lifetime, name='set_session_lifetime'),
视图
def set_session(req): # 默认过期时间为2周 req.session['name'] = 'lucky' req.session['age'] = '18' return HttpResponse('设置session def set_session_lifetime(req): # 过期时间为0 浏览会话结束时 req.session.set_expiry(0) # 设置session存活时间为1分钟 req.session.set_expiry(60) req.session['name'] = 'lucky' req.session['age'] = '18' return HttpResponse('设置session并设置过期时间')
在服务端设置session的时候,会发生下面这几件事情:
- 在浏览器请求服务端的时候,django内部自动生成了随机加密字符串
- 在django_session表中存入数据
- 响应走的时候有中间件帮你设置随机字符串给cookie
**提示1:**在服务端添加session值之前,必须要先将django需要用到的表用数据库的迁移命令迁移
**提示2:**这个django_session表中有三个字段
session_key : key 这个是要与浏览器中的cookie 匹配的内容,随机字符串
session_data: value 这个是用户真正的数据,加密数据
exprie_date:session 过期时间,django默认的是14天
-
方法
req.session.get(key)
-
实例
def get_session(req): val = req.session.get('name', 'default') return HttpResponse('获取session---'+val)
在获取浏览器的session时,会发生下面几件事情:
- 浏览器发送cookie到django后端之后,django会自动获取到cookie值
- 拿着随机字符串去django_session表中比对,是否有对应的数据
- 如果比对上了,就将随机字符串所对应的数据,取出并将数据解密,给request.session 如果对不上,那么request.session就是个空
方法:
-
pop() 通过key删除值
-
del req.session[key] 删除指定的key
-
clear() 清除当前用户的session数据
-
flush() 一般用于退出 清空session表中的数据
-
logout(req) 退出 清空session表中的数据
from django.contrib.auth import logout
-
clear_expired() 清除过期的session
实例
def delete_session(req):
req.session.pop('name')
del req.session['name']
req.session.clear()
req.session.flush()
logout(req)
req.session.clear_expired()
return HttpResponse('删除session')
# 获取、设置、删除Session中数据
request.session['k1']
request.session.get('k1',None)
request.session['k1'] = 123
request.session.setdefault('k1',123) # 存在则不设置
del request.session['k1']
# 所有 键、值、键值对
request.session.keys()
request.session.values()
request.session.items()
request.session.iterkeys()
request.session.itervalues()
request.session.iteritems()
# 会话session的key
request.session.session_key
# 将所有Session失效日期小于当前日期的数据删除
request.session.clear_expired()
# 检查会话session的key在数据库中是否存在
request.session.exists("session_key")
SESSION_ENGINE = 'django.contrib.sessions.backends.db' # 引擎(默认)
也可以改为使用mysql
SESSION_ENGINE = 'django.contrib.sessions.backends.mysql'
SESSION_ENGINE = 'django.contrib.sessions.backends.cache' # 引擎
SESSION_CACHE_ALIAS = 'default' # 使用的缓存别名(默认内存缓存,也可以是memcache),此处别名依赖缓存的设置
SESSION_ENGINE = 'django.contrib.sessions.backends.file' # 引擎
SESSION_FILE_PATH = '/home/xlg/桌面/session_cache' # 缓存文件路径,如果为None,则使用tempfile模块获取一个临时地址tempfile.gettempdir()
SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db' # 引擎
优先查找内存,不在则去数据库中查找
- 安装
sudo pip install redis
sudo pip install django-redis-sessions==0.5.6
- 配置
# 更改存储在redis中
SESSION_ENGINE = 'redis_sessions.session'
# 主机
SESSION_REDIS_HOST = '127.0.0.1'
# 端口
SESSION_REDIS_PORT = '6379'
# 数据库
SESSION_REDIS_DB = 0
SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies' # 引擎
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 = 60 * 60 * 24 * 7 * 2 # Session的cookie失效日期(2周)(默认)
SESSION_EXPIRE_AT_BROWSER_CLOSE = False # 是否关闭浏览器使得Session过期(默认)
SESSION_SAVE_EVERY_REQUEST = False # 是否每次请求都保存Session,默认修改之后才保存(默认)