Django
1. cookie session
1. 简介
1. 网站都没有保存用户功能的需求 所有用户访问返回的结果都是一样的
eg
: 新闻、博客、文章
...
2. 出现了一些需要保存用户信息的网站
eg
: 淘宝、支付宝、京东
...
如果不保存用户登陆状态 也就意味着用户每次访问网站都需要重复的输入用户名和密码
(你觉得这样的网站你还想用吗?
)
当用户第一次登陆成功之后 将用户的用户名密码返回给用户浏览器 让用户浏览器保存在本地,之后访问网站的时候浏览器自动将保存在浏览器上的用户名和密码发送给服务端,服务端获取之后自动验证
早先这种方式具有非常大的安全隐患
优化
:
当用户登陆成功之后,服务端产生一个随机字符串
(在服务端保存数据
,用kv键值对的形式
),交由客户端浏览器保存
随机字符串
1:用户
1相关信息
随机字符串
2:用户
2相关信息
随机字符串
3:用户
3相关信息
之后访问服务端的时候,都带着该随机字符串,服务端去数据库中比对是否有对应的随机字符串从而获取到对应的用户信息
但是如果你拿到了截获到了该随机字符串,那么你就可以冒充当前用户 其实还是有安全隐患的
要知道在web领域没有绝对的安全也没有绝对的不安全
存在客户端浏览器上的键值对
服务端保存在客户端浏览器上的信息都可以称之为cookie
它的表现形式一般都是k
:v键值对
(可以有多个
)
存在服务端的键值对
数据是保存在服务端的并且它的表现形式一般也是k
:v键值对
(可以有多个
)
加密的键值对 如果放在客户端浏览器上 它就叫cookie 服务端签发的加密字符串
session虽然数据是保存在服务端的 但是禁不住数据量大
token 服务端不再保存数据
登陆成功之后 将一段用户信息进行加密处理
将加密之后的结果拼接在信息后面 整体返回给浏览器保存
浏览器下次访问的时候带着该信息 服务端自动切去前面一段信息再次使用自己的加密算法
跟浏览器尾部的密文进行比对
1. cookie 就是保存在客户端浏览器上的信息
2. session 就是保存在服务端上的信息
3. session 是基于cookie工作的
(其实大部分的保存用户状态的操作都需要使用到cookie
)
2. cookie
HTTP协议是无状态的
,无状态的意思是每次请求都是独立的,它的执行情况和结果与前面的请求和之后的请求都无直接关系,它不会受前面的请求响应情况直接影响,也不会直接影响后面的请求响应情况。
一句有意思的话来描述就是人生只如初见,对服务器来说,每次的请求都是全新的。
状态可以理解为客户端和服务器在某次会话中产生的数据,那无状态的就以为这些数据不会被保留。会话中产生的数据又是我们需要保存的,也就是说要“保持状态”。因此Cookie就是在这样一个场景下诞生
其实Cookie是key
-value结构,类似于一个python中的字典。
随着服务器端的响应发送给客户端浏览器。
然后客户端浏览器会把Cookie保存起来,当下一次再访问服务器时把Cookie再发送给服务器。
Cookie是由服务器创建,然后通过响应发送给客户端的一个键值对。
客户端会保存Cookie,并会标注出Cookie的来源(哪个服务器的Cookie)。
当客户端向服务器发出请求时,会把所有这个服务器Cookie包含在请求中发送给服务器,这样服务器就可以识别客户端了
注意,不同浏览器之间是不共享Cookie的。
由服务器产生内容,浏览器收到请求后保存在本地
当浏览器再次访问时,浏览器会自动带上Cookie,这样服务器就能通过Cookie的内容来判断这个是“谁”了。
Cookie大小上限为4KB
一个服务器最多在客户端浏览器上保存
20个Cookie
一个浏览器最多保存
300个Cookie
如果服务器端发送重复的Cookie那么会覆盖原有的Cookie
例如
:
客户端的第一个请求服务器端发送的Cookie是:Set
-Cookie
: a
=A
第二个请求服务器端发送的Cookie是:Set
-Cookie
: a
=AA,那么客户端只留一个Cookie,即:a
=AA。
浏览器中按F12 点击 network cookies就能看到
3. session
Cookie虽然在一定程度上解决了“保持状态”的需求,但是由于Cookie本身最大支持
4096字节,以及Cookie本身保存在客户端,可能被拦截或窃取,因此就需要有一种新的东西,它能支持更多的字节,并且保存在服务器,有较高的安全性,这就是Session。
基于HTTP协议的无状态特征,服务器根本就不知道访问者是“谁”。那么上述的Cookie就起到桥接的作用
我们可以给每个客户端的Cookie分配一个唯一的
id,这样用户在访问时,通过Cookie,服务器就知道来的人是“谁”。然后我们再根据不同的Cookie的
id,在服务器上保存一段时间的私密资料,如“账号密码”等等。
Cookie弥补了HTTP无状态的不足,让服务器知道来的是“谁”;但是Cookie以文本的形式保存在本地,自身安全性较差;所以我们就通过Cookie识别不同的用户,对应的在Session里保存私密的信息以及超过
4096字节的文本
另外,上述所说的Cookie和Session其实是共通性的东西,不限于语言和框架。
4. 会话
会话可以理解为客户端与服务器之间的一次会晤,在一次会晤中可能会包含多次请求和响应。
例如
:
你给
10086打个电话,你就是客户端,而
10086服务人员就是服务器
从双方接通电话那一刻起,会话就开始了,到某一方挂断电话表示会话结束
在通话过程中,你会向
10086发出多个请求,那么这多个请求都在一个会话中
在Web中,客户向某一服务器发出第一个请求开始
,会话就开始了
,直到客户关闭了浏览器
,会话结束
在一个会话的多个请求中共享数据,这就是会话跟踪技术
例如
:
在一个会话中的请求如下:
请求银行主页
请求登录(请求参数是用户名和密码)
请求转账(请求参数与转账相关的数据)
请求信用卡还款(请求参数与还款相关的数据)
在上述会话中当前用户信息必须在这个会话中共享的,因为登录的是张三,那么在转账和还款时一定是相对张三的转账和还款!这就说明我们必须在一个会话过程中有共享数据的能力。
HTTP协议是无状态协议,也就是说每个请求都是独立的
,无法记录前一次请求的状态
但HTTP协议中可以使用Cookie来完成会话跟踪
在Web开发中,使用session来完成会话跟踪,session底层依赖Cookie技术
2. django中cookie的使用
'''
虽然cookie是服务端告诉客户端浏览器需要保存内容
但是客户端浏览器可以选择拒绝保存
如果禁止了 那么只要是需要记录用户状态的网站登陆功能都无法使用了
'''
return HttpResponse
()
return render
()
return redirect
()
obj1
= HttpResponse
()
return obj1
obj2
= render
()
return obj2
obj3
= redirect
()
return obj3
1. obj
.set_cookie
(key
,value
)
2. obj
.set_signed_cookie
(key
,value
,salt
='加密盐')
1. request
.COOKIES
.get
(key
)
2. request
.get_signed_cookie
(key
,
default
=RAISE_ERROR
,
salt
='',
max_age
=None
)
obj
.delete_cookie
(key
)
obj
.set_cookie
('username', 'jason666',max_age
=3,expires
=3)
max_age expires
两者都是设置超时时间的 并且都是以秒为单位
需要注意的是 针对IE浏览器需要使用expires
def cookie_test(request
):
obj
=HttpResponse
('ok')
obj
.set_cookie
('name','egon')
obj
.set_cookie
('age','19')
return obj
def get_cookie(request
):
print(request
.COOKIES
)
print(request
.COOKIES
.get
('name'))
return HttpResponse
('我拿了你传过来的cookie')
def delete_cookie(request
):
obj
=HttpResponse
('我删掉了你name这个cookie ')
obj
.delete_cookie
('name')
return obj
3. cookie版登陆校验
1. 路由
path
('login/', views
.login
),
path
('order/', views
.order
),
path
('logout/', views
.logout
),
path
('userinfo/', views
.userinfo
),
2. 视图
"""
需求分析:
用户如果在没有登陆的情况下想访问一个需要登陆的页面
那么先跳转到登陆页面 当用户输入正确的用户名和密码之后
应该跳转到用户之前想要访问的页面去
"""
1. 示例一
def login_auth(func
):
def inner(request
, *args
, **kwargs
):
name
= request
.COOKIES
.get
('name')
if name
:
res
= func
(request
, *args
, **kwargs
)
return res
else:
path
= request
.get_full_path
()
return redirect
('/login/?returnUrl=%s' % path
)
return inner
def login(request
):
if request
.method
== 'GET':
return render
(request
, 'login.html')
else:
name
= request
.POST
.get
('name')
password
= request
.POST
.get
('password')
if name
== 'lqz' and password
== '123':
path
= request
.GET
.get
('returnUrl')
if path
:
obj
= redirect
(path
)
else:
obj
= redirect
('/home/')
obj
.set_cookie
('name', name
)
return obj
else:
return HttpResponse
('用户名或密码错误')
@login_auth
def order(request
):
return render
(request
, 'order.html')
@login_auth
def userinfo(request
):
return render
(request
, 'userinfo.html')
def logout(request
):
obj
= HttpResponse
('退出登录成功')
obj
.delete_cookie
('name')
return obj
2. 示例二
def login_auth(func
):
def inner(request
,*args
,**kwargs
):
target_url
= request
.get_full_path
()
if request
.COOKIES
.get
('username'):
return func
(request
,*args
,**kwargs
)
else:
return redirect
('/login/?next=%s'%target_url
)
return inner
def login(request
):
if request
.method
== 'POST':
username
= request
.POST
.get
('username')
password
= request
.POST
.get
('password')
if username
== 'jason' and password
== '123':
target_url
= request
.GET
.get
('next')
if target_url
:
obj
= redirect
(target_url
)
else:
obj
= redirect
('/home/')
obj
.set_cookie
('username', 'jason666')
"""
浏览器不单单会帮你存
而且后面每次访问的时候还会带着它过来
"""
return obj
return render
(request
,'login.html')
@login_auth
def home(request
):
return HttpResponse
("我是home页面,只有登陆的用户才能进来哟~")
3. 模板
1. login.html
<form action="" method="post">
<p>用户名:
<input type="text" name="name"></p>
<p>密码:
<input type="password" name="password"></p>
<p><input type="submit" value="提交"></p>
</form>
2. order.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title
</title>
</head>
<body>
<a href="/logout/">点我退出
</a>
</body>
</html>
3. userinfo.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title
</title>
</head>
<body>
<h1>用户信息页面
</h1>
</body>
</html>
4. django中session的使用
1. 存在于服务端的键值对
session数据是保存在服务端的,给客户端返回的是一个随机字符串
sessionid
: 随机字符串
2. 同一个浏览器不允许登录多个账户,不同浏览器可以登录同一个账户
3. session的使用(必须迁移数据)
python manage
.py makemigrations
python manage
.py migrate
request
.session
['key'] = value
request
.session
.get
('key')
request
.session
.set_expiry
()
1. 整数 多少秒 session会在些秒数后失效
2. 日期对象 到指定日期就失效
3. 0 一旦当前浏览器窗口关闭立刻失效
4. None 失效时间就取决于django内部全局session默认的失效时间
request
.session
.delete
()
request
.session
.flush
()
增:request
.session
['name']=lqz
查:request
.session
['name']
改:request
.session
['name']=egon
删:
del request
.session
['name']
设置过期时间:request
.session
.set_expiry
(10)
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
request
.session
.clear_expired
()
request
.session
.exists
("session_key")
request
.session
.delete
()
request
.session
.flush
()
5. django_session表
django_session表中的数据条数是取决于浏览器的
同一个计算机上
(IP地址
)同一个浏览器只会有一条数据生效
当session过期的时候可能会出现多条数据对应一个浏览器,但是该现象不会持续很久
内部会自动识别过期的数据清除 你也可以通过代码清除
主要是为了节省服务端数据库资源
6. 示例
: 设置session
request
.session
['hobby'] = 'girl'
"""
运行代码 内部发生的事情
1. django内部会自动帮你生成一个随机字符串
2. django内部自动将随机字符串和对应的数据存储到django_session表中
1. 先在内存中产生操作数据的缓存
2. 在响应结果django中间件的时候才真正的操作数据库
3. 将产生的随机字符串返回给客户端浏览器保存
"""
7. 示例
: 获取session
request
.session
.get
('hobby')
"""
运行代码 内部发生的事情
1. 自动从浏览器请求中获取sessionid对应的随机字符串
2. 拿着该随机字符串去django_session表中查找对应的数据
3. 校验
1. 如果比对上了 则将对应的数据取出并以字典的形式封装到request.session中
2. 如果比对不上 则request.session.get()返回的是None
"""
5. django中session的配置
def set_cookie(self
,
key
,
value
='',
max_age
=None,
expires
=None, path
='/',
domain
=None,
secure
=False,
httponly
=False
)
1. 数据库Session
SESSION_ENGINE
= 'django.contrib.sessions.backends.db'
2. 缓存Session
SESSION_ENGINE
= 'django.contrib.sessions.backends.cache'
SESSION_CACHE_ALIAS
= 'default'
3. 文件Session
SESSION_ENGINE
= 'django.contrib.sessions.backends.file'
SESSION_FILE_PATH
= None
4. 缓存
+数据库
SESSION_ENGINE
= 'django.contrib.sessions.backends.cached_db'
5. 加密Cookie Session
SESSION_ENGINE
= 'django.contrib.sessions.backends.signed_cookies'
6. 其他公用设置项
SESSION_COOKIE_AGE
= 1209600
SESSION_EXPIRE_AT_BROWSER_CLOSE
= False
SESSION_COOKIE_NAME =
"sessionid"
SESSION_COOKIE_PATH =
"/"
SESSION_COOKIE_DOMAIN
= None
SESSION_COOKIE_SECURE
= False
SESSION_COOKIE_HTTPONLY
= True
SESSION_SAVE_EVERY_REQUEST
= False
6. CBV加装饰器
from django
.views
import View
from django
.utils
.decorators
import method_decorator
class UserInfo(View
):
@method_decorator
(login_auth
)
def dispatch(self
, request
, *args
, **kwargs
):
return super().dispatch
(request
,*args
,**kwargs
)
@method_decorator
(login_auth
)
def get(self
, request
, *args
, **kwargs
):
return HttpResponse
('userinfo get')
def post(self
,request
):
return HttpResponse
('post请求')
1. 加在类上: @method_decorator
(login_auth
,name
='get')
2. 加在方法上
: @method_decorator
(login_auth
)