为什么需要cookie呢?http协议是无状态的,不会记住客户端的信息,断开之后,再次连接就需要重新认证,比如我们浏览淘宝,首先先登录,看到主页,然后点击购物车,还要登录,然后跳转,点击收藏夹,还要登录,然后跳转,用户体验感不好。
你想访问一个网站,先登录,登录之后,这个网站给你提供的所有的可选项页面都可以访问,不用在登陆了。
带有cookie的访问过程
cookie为什么这么做?
cookie称之为小甜点,相当于一个证明。避免你们重复的输入用户名密码。
是因为http协议的无状态特性,避免我们重复性登录,才出现了cookie的概念
首先来讲,cookie是浏览器的技术,cookie具体指的是一小段信息,它是服务器发送出来存储在浏览器上的一组组键值对,可以理解为服务端给客户端的小甜点,下次访问服务器时浏览器会自动携带这些键值对,以便服务器提取有用信息。
cookie的工作原理:浏览器访问服务器,带着一个空的cookie,然后由服务器产生内容,浏览器收到响应后将返回cookie的内容保存在本地;当浏览器再次访问时,浏览器会自动带上cookie,这样服务器就能通过cookie的内容来判断这个是’谁‘了。
cookie最多存储4kb的信息。(缺点之一)
一个服务器最多在客户端浏览器上保存20个cookie。不同种类的信息存储在不同的cookie字典中,一个服务器最多只能设置20个cookie。
一个浏览器最多保存300个cookie,因为一个浏览器可以访问多个服务器。
不同的浏览器各自持有自己的cookie表,互相不能访问。你在谷歌浏览器登陆过淘宝,如果你打开IE浏览器,IE浏览器是不能打开你的京东cookie表用于自动登录。
同一个浏览器,访问同一个网站,只能登录一个用户。
情况1:第二个用户会把第一个用户顶掉。
情况2:不允许第二个用户登录。(需要先把第一个用户退出)
原理:
重新创建一个项目
验证cookie的流程
浏览器访问服务端,带着一个空cookie,然后由服务器产生内容,浏览器收到响应后将cookie的内容保存在本地;当浏览器再次访问时,浏览器会自动带上cookie,这样服务器就能通过cookie的内容来判断这个是“谁”了。
如何判断是一个网站下面的页面?ip+端口相同,我们就可以认定他们同属于一个网站的页面。接下来,我给index页面设置一些cookie键值对,访问其他页面时,浏览器的请求头中cookie都会带有这些键值对。
第一次访问index.html页面时,查看cookie里面的内容,只有默认携带的键值对。
访问一下page页面以及shopping页面:
除了Django后端默认添加的键值对意外,没有其他的键值对。
def index(request):
ret = render(request, ‘index.html‘)
ret.set_cookie(‘k1‘, ‘v1‘),
ret.set_cookie(‘name‘, ‘dong‘),
return ret
然后在访问其他的页面:page页面以及shopping页面去哪都带有这个k1:v1
,name:dong
键值对。
只要我在后端设置了好一些cookie键值对,浏览器再访问网站的其他页面时,都会带有设置这些键值对。
后端获取cookie键值对
def shopping(request):
# 获取cookie键值对
print(request.COOKIES)
‘‘‘
{‘csrftoken‘: ‘bPaKN0LiZdQniTezmCSQneZRl6dNg6wLe9aVL0UkD7qoXXL7vl0WjtJ42OIhv5Bz‘, ‘k1‘: ‘v1‘, ‘name‘: ‘dong‘}
‘‘‘
print(request.COOKIES.get(‘k1‘)) # v1
return render(request, ‘shopping.html‘)
先构建之前的登录跳转功能
def login(request):
if request.method == ‘GET‘:
return render(request, ‘login.html‘)
else:
name = request.POST.get(‘username‘)
password = request.POST.get(‘password‘)
?
if name == ‘dong‘ and password == ‘123‘:
return redirect(‘home‘)
else:
return redirect(‘login‘)
?
def home(request):
return render(request, ‘home.html‘)
?
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>请先登录</h1>
?
<form action="" method="post">
{% csrf_token %}
用户名:<input type="text" name="username">
<p></p>
密码:<input type="password" name="password">
<p></p>
<input type="submit">
</form>
</body>
</html>
这个的坑是不登陆的情况下,照样可以访问home页面
def login(request):
if request.method == ‘GET‘:
return render(request, ‘login.html‘)
else:
name = request.POST.get(‘username‘)
password = request.POST.get(‘password‘)
?
if name == ‘dong‘ and password == ‘123‘:
ret = redirect(‘home‘)
ret.set_cookie(‘is_login‘, ‘True‘)
return ret
else:
return redirect(‘login‘)
?
?
def home(request):
if request.COOKIES.get(‘is_login‘) == ‘True‘:
return render(request, ‘home.html‘)
return redirect(‘login‘)
?
?
def page(request):
if request.COOKIES.get(‘is_login‘) == ‘True‘:
return render(request, ‘page.html‘)
return redirect(‘login‘)
上面的代码写的太low了,怎么简化?我们可以加上装饰器
def login(request):
if request.method == ‘GET‘:
return render(request, ‘login.html‘)
else:
name = request.POST.get(‘username‘)
password = request.POST.get(‘password‘)
?
if name == ‘dong‘ and password == ‘123‘:
ret = redirect(‘home‘)
ret.set_cookie(‘is_login‘, ‘True‘)
return ret
else:
return redirect(‘login‘)
?
?
def wrapper(func):
def inner(request, *args, **kwargs):
if request.COOKIES.get(‘is_login‘) == ‘True‘:
ret = func(request, *args, **kwargs)
return ret
else:
return redirect(‘login‘)
return inner
原文:https://www.cnblogs.com/muyangxiaodong/p/13154038.html