Django之cookie

cookie定义及组成

对于Cookie的定义,跟语言没有关系的,不管Server端用的是Java、Python等后端语言哪一种,涉及到web开发相关知识时候,必须了解这方面知识。

定义

Cookie 并不是它的原意“甜饼”的意思, 而是一个保存在客户机中的简单的文本文件, 这个文件与特定的 Web 文档关联在一起, 保存了该客户机访问这个Web 文档时的信息, 当客户机再次访问这个 Web 文档时这些信息可供该文档使用。由于“Cookie”具有可以保存在客户机上的神奇特性, 因此它可以帮助我们实现记录用户个人信息的功能, 而这一切都不必使用复杂的CGI等程序 [2] 。
举例来说, 一个 Web 站点可能会为每一个访问者产生一个唯一的ID, 然后以 Cookie 文件的形式保存在每个用户的机器上。如果使用浏览器访问 Web, 会看到所有保存在硬盘上的 Cookie。在这个文件夹里每一个文件都是一个由“名/值”对组成的文本文件,另外还有一个文件保存有所有对应的 Web 站点的信息。在这里的每个 Cookie 文件都是一个简单而又普通的文本文件。透过文件名, 就可以看到是哪个 Web 站点在机器上放置了Cookie(当然站点信息在文件里也有保存)

组成:

Cookie是一段不超过4KB的小型文本数据,由一个名称(Name)、一个值(Value)和其它几个用于控制Cookie有效期、安全性、使用范围的可选属性组成。其中 [3] :
(1)Name/Value:设置Cookie的名称及相对应的值,对于认证Cookie,Value值包括Web服务器所提供的访问令牌 [3] 。
(2)Expires属性:设置Cookie的生存期。有两种存储类型的Cookie:会话性与持久性。Expires属性缺省时,为会话性Cookie,仅保存在客户端内存中,并在用户关闭浏览器时失效;持久性Cookie会保存在用户的硬盘中,直至生存期到或用户直接在网页中单击“注销”等按钮结束会话时才会失效 [3] 。
(3)Path属性:定义了Web站点上可以访问该Cookie的目录 [3] 。
(4)Domain属性:指定了可以访问该 Cookie 的 Web 站点或域。Cookie 机制并未遵循严格的同源策略,允许一个子域可以设置或获取其父域的 Cookie。当需要实现单点登录方案时,Cookie 的上述特性非常有用,然而也增加了 Cookie受攻击的危险,比如攻击者可以借此发动会话定置攻击。因而,浏览器禁止在 Domain 属性中设置.org、.com 等通用顶级域名、以及在国家及地区顶级域下注册的二级域名,以减小攻击发生的范围 [3] 。
(5)Secure属性:指定是否使用HTTPS安全协议发送Cookie。使用HTTPS安全协议,可以保护Cookie在浏览器和Web服务器间的传输过程中不被窃取和篡改。该方法也可用于Web站点的身份鉴别,即在HTTPS的连接建立阶段,浏览器会检查Web网站的SSL证书的有效性。但是基于兼容性的原因(比如有些网站使用自签署的证书)在检测到SSL证书无效时,浏览器并不会立即终止用户的连接请求,而是显示安全风险信息,用户仍可以选择继续访问该站点。由于许多用户缺乏安全意识,因而仍可能连接到Pharming攻击所伪造的网站 [3] 。
(6)HTTPOnly 属性 :用于防止客户端脚本通过document.cookie属性访问Cookie,有助于保护Cookie不被跨站脚本攻击窃取或篡改。但是,HTTPOnly的应用仍存在局限性,一些浏览器可以阻止客户端脚本对Cookie的读操作,但允许写操作;此外大多数浏览器仍允许通过XMLHTTP对象读取HTTP响应中的Set-Cookie头

应用

从定义上来理解cookie,可以作为存储介质,存储一些必要的信息在客户端,当然这些重要的信息是在第一次在服务端设置到cookie里面,当第二次访问请求的时候,服务端通过cookie里面的值来判定是否有一些必要的数据,从而减轻了Server端的访问压力,也就是通过cookie来做了验证的操作。

举例说明:
模拟用户登录进入首页的操作:cookie里面存储用户username

  • 用户进入首页操作,通过cookie来判断,如果用户cookie已经存在username,就直接跳转到index页面,如果不存在就直接跳转到login登录界面
  • 登录界面的操作,在登录成功后,存储username值到cookie里面,用于下次直接访问首页index时判断是否已经登录了
    view中的逻辑代码如下:
user_info = {
    'test': {'pwd': "123123"},
}
def login(request):
    if request.method == "GET":
        return render(request, 'cookie_login.html')
    if request.method == "POST":
        u = request.POST.get('username')
        p = request.POST.get('pwd')
        dic = user_info.get(u)
        if not dic:
            return render(request, 'cookie_login.html')
        if dic['pwd'] == p:
            res = redirect('/cookietest/index/')
            res.set_cookie('username', u)  # 给重定向的url设cookie
            return res
        else:
            return render(request, 'cookie_login.html')
def index(reqeust):
    v = reqeust.COOKIES.get('username')  # 获取当前已经登录的用户
    if not v:  # 如果获取不到cookie表示没有登录
        return redirect('/cookietest/login/')
    return render(reqeust, 'cookie_test_index.html', {'current_user': v})

login和index页面分别如下:

cookie_login.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>cookie_test_login</title>
</head>
<body>
<form action="/cookietest/login/" method="POST">
    <input type="text" name="username" placeholder="用户名"/>
    <input type="password" name="pwd" placeholder="密码"/>
    <input type="submit"/>
</form>
</body>
</html>

cookie_test_index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Cookie_test_index</title>
</head>
<body>
    <h1>欢迎登录:{{ current_user }}</h1>
</body>
</html>

登录到进入首页后,看一下浏览器中的cookie有哪些值:
在这里插入图片描述
把👆demo跑起来,实际调试下浏览器,初步理解cookie是做什么。

Cookie 相关api

设置cookie 都是response.py里面的方法,比如上面用的就是第一种:res.set_cookie(‘username’, u)

  • 第一种:def set_cookie()
  • 第二种:def set_signed_cookie
HttpResponse(...) 或 rep = render(request, ...)
rep.set_cookie(key,value,...)
rep.set_signed_cookie(key,value,salt='加密盐',...)
    参数:
        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获取(不是绝对,底层抓包可以获取到也可以被覆盖)

取cookie
也有两种方法,其实针对不同的设置对应不同的获取方法,对于第二种加盐处理的算法,django已经为我们做了。

request.COOKIES['key']
request.get_signed_cookie(key, default=RAISE_ERROR, salt='', max_age=None)
    参数:
        default: 默认值
           salt: 加密盐
        max_age: 后台控制过期时间

上面的demo我们就是这样获取的:

v = reqeust.COOKIES.get('username')

分析流程

有没有发现👆的获取cookie和设置cookie是怎样的操作流程:

  • response里面设置cookie,返回到客户端【浏览器】
  • 通过request来获取cookie
  • cookie其实是存在客户端【浏览器里面的】
    所以我们是不是可以得到以下结论:
  • 在请求和响应的过程中,cookie其实就是在请求头里面的,所以Server端能够设置和获取
  • 既然在客户端,那么这个cookie其实也是可以在客户端进行重写的

优缺点

优点:

  1. http请求的无记忆性;
  2. 加快访问速度
  3. 减少服务器压力

缺点

  • 大小限制了,太小
  • 安全因素太低,一般通过加密和session共同使用
  • 客户端可能禁用cookie,导致cookie不可用

特点

  • cookies保存在客户端浏览器上的键值对,且每次访问页面都会带着cookies
  • cookies可以主动清除
  • cookies也可以被"伪造",可以被别人带着cookies操作你的账号
  • cookies会根据域名进行分类,不能跨域共享,也就是说百度有百度的,JD有京东的
  • cookies必须请求数据成功后才能有用哈
  • 浏览器可以设置不接收Cookies
  • 服务器端设置的cookies
  • cookies可以设置超时时间, max_age=10

完整Demo地址下载

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ItJavawfc

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值