Django中Cookie相关操作

简介: Django中Cookie相关操作

Cookie前置

会话跟踪

我们需要先了解一下什么是会话!可以把会话理解为客户端与服务器之间的一次会晤,在一次会晤中可能会包含多次请求和响应。

例如你给10086打个电话,你就是客户端,而10086服务人员就是服务器了。从双方接通电话那一刻起,会话就开始了,到某一方挂断电话表示会话结束。

在通话过程中,你会向10086发出多个请求,那么这多个请求都在一个会话中。 客户向某一服务器发出第一个请求开始,会话就开始了,直到客户关闭了浏览器会话结束。

在一个会话的多个请求中共享数据,这就是会话跟踪技术。例如在一个会话中的请求如下:

请求银行主页;

请求登录(请求参数是用户名和密码);

请求转账(请求参数与转账相关的数据);

请求信誉卡还款(请求参数与还款相关的数据)。

 在这个会话中当前用户信息必须在这个会话中共享的,因为登录的是张三,那么在转账和还款时一定是相对张三的转账和还款!

这就说明我们必须在一个会话过程中有共享数据的能力。而web中这种能力的实现就要依靠cookie和session

http协议

无状态: 不会记录任何客户端和服务端的信息

无连接(closed)(长连接(keepalive)): 一次请求一次响应,就断开连接了. 服务器的连接数是有限的

在早期的HTTP/1.0中,每次http请求都要创建一个连接,而创建连接的过程需要消耗资源和时间,为了减少资源消耗,缩短响应时间,就需要重用连接。

在后来的HTTP/1.0中以及HTTP/1.1中,引入了重用连接的机制,就是在http请求头中加入Connection: keep-alive来告诉对方这个请求响应完成后不要关闭,

下一次咱们还用这个请求继续交流。协议规定HTTP/1.0如果想要保持长连接,需要在请求头中加上Connection: keep-alive,而HTTP/1.1默认是支持长连接的,有没有这个请求头都行。

当然了,协议是这样规定的,至于支不支持还得看服务器(比如tomcat)和客户端(比如浏览器)的具体实现。

在实践过程中发现谷歌浏览器使用HTTP/1.1协议时请求头中总会带上Connection: keep-alive,

另外通过httpclient使用HTTP/1.0协议去请求tomcat时,即使带上Connection: keep-alive请求头也保持不了长连接。

如果HTTP/1.1版本的http请求报文不希望使用长连接,则要在请求头中加上Connection: close,接收到这个请求头的对端服务就会主动关闭连接。

但是http长连接会一直保持吗?肯定是不会的。一般服务端都会设置keep-alive超时时间。

超过指定的时间间隔,服务端就会主动关闭连接。同时服务端还会设置一个参数叫最大请求数,比如当最大请求数是300时,

只要请求次数超过300次,即使还没到超时时间,服务端也会主动关闭连接。

Cookie

1、Cookie的由来

大家都知道HTTP协议是无状态的。

无状态的意思是每次请求都是独立的,它的执行情况和结果与前面的请求和之后的请求都无直接关系,它不会受前面的请求响应情况直接影响,也不会直接影响后面的请求响应情况。


一句有意思的话来描述就是人生只如初见,对服务器来说,每次的请求都是全新的。


状态可以理解为客户端和服务器在某次会话中产生的数据,那无状态的就以为这些数据不会被保留。会话中产生的数据又是我们需要保存的,也就是说要“保持状态”。因此Cookie就是在这样一个场景下

诞生。

          并且还有一个问题就是,你登陆我的网站的时候,我没法确定你是不是登陆了,之前我们学的django,虽然写了很多页面,但是用户不用登陆都是可以看所有网页的,只要他知道网址就行,但是我们为了自己的安全机制,我们是不是要做验证啊,访问哪一个网址,都要验证用户的身份,但是还有保证什么呢,用户登陆过之后,还要保证登陆了的用户不需要再重复登陆,就能够访问我网站的其他的网址的页面,对不对,但是http无状态啊,怎么保证这个事情呢?此时就要找cookie了。

2、什么是Cookie

首先来讲,cookie是浏览器的技术,Cookie具体指的是一段小信息,它是服务器发送出来存储在浏览器上的一组组键值对,可以理解为服务端给客户端的一个小甜点,下次访问服务器时浏览器会自动携带这些键值对,以便服务器提取有用信息。

Cookie的原理

   cookie的工作原理是:浏览器访问服务端,带着一个空的cookie,然后由服务器产生内容,浏览器收到相应后保存在本地;当浏览器再次访问时,浏览器会自动带上Cookie,这样服务器就能通过Cookie的内容来判断这个是“谁”了。

cookie是浏览器技术,针对的就是http协议无状态,导致不能和服务端维持会话,例子:登录,登录之后,看到响应结果,继续访问其他有页面,服务端要判断我是谁.

3、查看Cookie

我们使用Chrome浏览器,打开开发者工具。   

cookie图解

4、Cookie规范

Cookie大小上限为4KB;

一个服务器最多在客户端浏览器上保存20个Cookie;

一个浏览器最多保存300个Cookie,因为一个浏览器可以访问多个服务器。

上面的数据只是HTTP的Cookie规范,但在浏览器大战的今天,一些浏览器为了打败对手,为了展现自己的能力起见,可能对Cookie规范“扩展”了一些,例如每个Cookie的大小为8KB,最多可保存500个Cookie等!但也不会出现把你硬盘占满的可能!

注意,不同浏览器之间是不共享Cookie的。也就是说在你使用IE访问服务器时,服务器会把Cookie发给IE,然后由IE保存起来,当你在使用FireFox访问服务器时,不可能把IE保存的Cookie发送给服务器。

Cookie与HTTP头

   Cookie是通过HTTP请求和响应头在客户端和服务器端传递的:

Cookie:请求头,客户端发送给服务器端;

格式:Cookie: a=A; b=B; c=C。即多个Cookie用分号离开;  Set-Cookie:响应头,服务器端发送给客户端;

一个Cookie对象一个Set-Cookie: Set-Cookie: a=A Set-Cookie: b=B Set-Cookie: c=C

Cookie的覆盖

   如果服务器端发送重复的Cookie那么会覆盖原有的Cookie,例如客户端的第一个请求服务器端发送的Cookie是:Set-Cookie: a=A;第二请求服务器端发送的是:Set-Cookie: a=AA,那么客户端只留下一个Cookie,即:a=AA。

新建个项目django_cookie先把csrf注释了,因为它影响cookie实验

视图函数

from django.http import HttpResponse
from django.shortcuts import render, redirect

from django.views import View

# Create your views here.


def login(request):
    method = request.method
    if method == 'GET':
        return render(request,'login.html')
    else:
        username = request.POST.get('username')
        password = request.POST.get('password')

        if username == 'root' and password == '123':
            return redirect('home')
        return HttpResponse('用户名或密码有误')



class Home(View):
    def get(self,request):
        return render(request,'home.html')


def cart(request):
    cart_lst = ['茅台','劳力士','拉菲','兰博基尼','库里南']
    return render(request,'cart.html',{'data':cart_lst})

登录页面

首页

购物车

但是这样有个问题,如果用户记住网址,可以绕过灯枯直接访问首页和购物车,所以这样很不安全

访问首页和购物车需要验证才更合理,此时就可以借助cookie

目前,我们没有设置cookie

5、django中操作cookie

设置Cookie

rep = HttpResponse(…)

rep = render(request, …)

rep.set_cookie(key,value,…)

rep.set_signed_cookie(key,value,salt=‘加密盐’, max_age=None, …)

参数:

key, 键

value=‘’, 值

max_age=None, 超时时间

expires=None, 超时时间(IE requires expires, so set it if hasn’t been already.)

path=‘/’, Cookie生效的路径,/ 表示根路径,特殊的:根路径的cookie可以被任何url的页面访问

domain=None, Cookie生效的域名

secure=False, https传输

httponly=False 只能http协议传输,无法被JavaScript获取(不是绝对,底层抓包可以获取到也可以被覆盖)

signed_cookie 只是加了签名的 cookie, 而不是被加密的 cookie.

signed_cookie 的作用是防止用户私自纂改.参考: Securing Web Cookies With Signatures

So once I’ve logged in, we set a username cookie containing “Michael Brunton-Spall”, or uid=1 or something.

The problem with this is that the user is in total control of this cookie

单纯的记录 uid 或者用户名在 cookie 中很容易被篡改(也是不建议将用户敏感信息记录在cookie中的原因), 万一攻击者把uid=1换成uid=2岂不是可以访问 uid=2用户的资源了吗? 而如果换成uid=2:1fPjh2:iQGDDYNcgSYkIFqa2ixqakj6-gI那么服务端不仅检验uid, 还检验uid=2后面的签名字段, 即是调用HttpRequest.get_signed_cookie(key=key, salt=salt), 这样即使用户把 cookie 中的 value 换成 uid=2, 但是没有签名, 服务端照样拒绝访问资源.

另外, Django 的 cookie 签名是用的Base64_with_hmac, 参考: Source code for django.core.signing

如果需要在 cookie 里设置被加密的 value, 需要自行对 value 进行加密(好像只能是对称加密), 比如使用hashlib.sha256{参考: hashlib — Secure hashes and message digests}:

set_cookie方法源码:

max_age和expires不能同时使用

设置cookie案例,我们在home页面设置

没设置之前,我们访问home页面,请求信息里面不带cookie

设置cookie

重启服务器,访问home页面

可以看到浏览器就包含了我们设置的cookie,这个是响应的cookie,浏览器将cookie保存到本地

响应头里面包含我们设置的响应cookie键值对

设置cookie的第一次访问,请求里面是不带cookie的

第二次访问,可以看到请求头已经包含了cookie,浏览器自动将cookie键值对加到请求头里面

此时浏览器的cookie既包含请求cookie,也包含响应cookie。因为home设置的cookie还会响应回来,相同的键是更新cookie

我们访问购物车,请求头也带着cookie,但是home页面设置的cookie

此时只包含请求cookie,没有响应cookie,因为cart页面没设置cookie

第一次访问带上cookie后,只要访问这个网站的不管什么页面,都会带上cookie

现在每个页面都能自由访问,这是不应该的,应该做认证

获取Cookie

request.COOKIES[‘key’] request.COOKIES.get(‘key’)

request.get_signed_cookie(key, default=RAISE_ERROR, salt=‘’, max_age=None) #获取签名cookie

参数:

default: 默认值

salt: 加密盐

max_age: 后台控制过期时间

也可以通过request.META 来获取请求头键值对

request.META 字典类型数据,所有的请求头的键都加上了一个HTTP_键名称,键值全部是大写

针对cookie,我们不用META。可以用专门的request.COOKIES.get(‘key’) 来获取cookie

在登录处。登录成功设置cookie。购物车和home都添加cookie验证,没有登录不让看页面,直接跳转到登录页面

封装个验证方法

此时登录购物车网址,直接跳转到登录页面

不包含任何cookie


登录成功

然后再次访问购物车,携带cookie,不用再次登录

可以看到cookie是字典类型数据

6、修改Cookie

在设置cookie的地方,保持键不变,值改一下 就是修改cookie。修改后重启服务,再次登录

此时,再点击购物车,由于携带的cookie发生变化,不满足原来的判断条件,已经不能在进入购物车界面

所以一旦修改cookie,记得在判断处也要及时同步做好修改

整个流程

浏览器自动将每个网站的cookie保存到了客户端本地

网址1: {xx:oo,xx1:oo1}

网址2: {xx:oo,xx1:oo1}

网址3: {xx:oo,xx1:oo1}

每次请求对应网址时,都会自动携带这个网址对应的cookie数据,放到http请求头部信息中.

cookie是浏览器技术,如果自己写的爬虫去爬页面,去模拟浏览器请求,是不会携带cookie的

可以自己想办法获取cookie:

模拟登录上网站,拿到cookie后,后面的请求携带上cookie

现在只要登录过一次,再次打开网站都能访问,这样很不安全。怎么办呢?

cookie要设置有效期,甚至删除cookie操作

原码,max_age表示超时时间

max_age和expires不能同时使用

7、设置cookie超时时间

浏览器登录,可以看到cookie有个有效期

过了时间cookie就被删除,需要重新登录

8、删除Cookie

退出登录时使用

def logout(request):

rep = redirect(“/login/”)

rep.delete_cookie(“user”) # 删除用户浏览器上之前设置的user cookie值

return rep

前端url反向解析


点登出后,再次访问购物车页面,cookie已被删除,需要重新登录

使用cookie关闭浏览器后,再次登录,之前的cookie会全部清除

cookie设置中文时的编码问题:cookie在设置时不允许出现中文。非要设置中文的怎么办,看下面的解决方案:

Cookie规范

Cookie大小上限为4KB;

一个服务器最多在客户端浏览器上保存20个Cookie;

一个浏览器最多保存300个Cookie,因为一个浏览器可以访问多个服务器。

上面的数据只是HTTP的Cookie规范,但在浏览器大战的今天,一些浏览器为了打败对手,为了展现自己的能力起见,可能对Cookie规范“扩展”了一些,例如每个Cookie的大小为8KB,最多可保存500个Cookie等!但也不会出现把你硬盘占满的可能!

注意,不同浏览器之间是不共享Cookie的。也就是说在你使用IE访问服务器时,服务器会把Cookie发给IE,然后由IE保存起来,当你在使用FireFox访问服务器时,不可能把IE保存的Cookie发送给服务器。

cookie设置的数据是明文存储在客户端的,不安全

由于cookie存储数据的大小有限制,并且明文存贮,看上去不安全.出现了session


相关文章
|
4天前
|
JavaScript 前端开发 Java
【JavaEE】使Cookie与Session失效-Servlet上传文件操作-优化表白墙(下)
【JavaEE】使Cookie与Session失效-Servlet上传文件操作-优化表白墙
7 0
|
4天前
|
存储 前端开发 Java
【JavaEE】使Cookie与Session失效-Servlet上传文件操作-优化表白墙(上)
【JavaEE】使Cookie与Session失效-Servlet上传文件操作-优化表白墙
8 0
|
4天前
|
存储 JavaScript 前端开发
JavaScript DOM 操作:解释一下 cookie、sessionStorage 和 localStorage 的区别。
Cookie是服务器发送至客户端的文本信息,会随每个请求发送回服务器,适合控制会话状态但可能暴露隐私。SessionStorage仅在当前会话中存储数据,关闭浏览器后清除,适合临时存储如登录状态。LocalStorage则持久保存数据,即使关闭浏览器也不会清除,适用于存储长期设置。三种方式各有侧重,应按需求选择。
17 0
|
4天前
|
存储 安全 搜索推荐
Django中Cookie和Session的使用
Django中Cookie和Session的使用
22 0
|
8月前
|
存储 JavaScript
js -cookie的操作
cookie是存储在客户端浏览器中的一段文本信息。
|
4天前
|
中间件 开发工具 数据安全/隐私保护
Django实践-05Cookie和Session
Django实践-05Cookie和Session
Django实践-05Cookie和Session
|
4天前
|
存储 前端开发 Java
【源码共读】在前端如何操作 Cookie
【源码共读】在前端如何操作 Cookie
66 1
|
6月前
|
存储 JavaScript 前端开发
cookie相关操作
cookie相关操作
35 0
|
8月前
|
存储 JSON 安全
跨越HTTP无状态边界:Cookie与Session在Django中的实战应用
跨越HTTP无状态边界:Cookie与Session在Django中的实战应用
29 0
|
9月前
|
Python