• 【Django】cookie和session


    cookie和session

    参考:https://www.cnblogs.com/yuanchenqi/articles/5716193.html

    通俗理解cookie:

    浏览器访问服务器的网站时,进入登录界面 登录成功,服务器发给浏览器一个cookie,浏览器将cookie保存在本地磁盘上。当浏览器再访问该网站的页面(如购物车)时发送的request请求会携带cookie 服务器识别到请求的cookie与自己数据库中cookie相同 则允许用户继续访问,否则会自动跳到登录页面。

    详细解释cookie和session

    1、cookie不属于http协议范围,由于http协议无法保持状态,但实际情况,我们却又需要“保持状态”,因此cookie就是在这样一个场景下诞生。
    
    cookie的工作原理是:由服务器产生内容,浏览器收到请求后保存在本地;当浏览器再次访问时,浏览器会自动带上cookie,这样服务器就能通过cookie的内容来判断这个是“谁”了。
    
    2、cookie虽然在一定程度上解决了“保持状态”的需求,但是由于cookie本身最大支持4096字节(约4Kb),以及cookie本身保存在客户端,可能被拦截或窃取,因此就需要有一种新的东西,它能支持更多的字节,并且他保存在服务器,有较高的安全性。这就是session。
    
    问题来了,基于http协议的无状态特征,服务器根本就不知道访问者是“谁”。那么上述的cookie就起到桥接的作用。
    
    我们可以给每个客户端的cookie分配一个唯一的id,这样用户在访问时,通过cookie,服务器就知道来的人是“谁”。然后我们再根据不同的cookie的id,在服务器上保存一段时间的私密资料,如“账号密码”等等。
    
    3、总结而言:cookie弥补了http无状态的不足,让服务器知道来的人是“谁”;但是cookie以文本的形式保存在本地,自身安全性较差;所以我们就通过cookie识别不同的用户,对应的在session里保存私密的信息以及超过4096字节的文本。
    
    4、另外,上述所说的cookie和session其实是共通性的东西,不限于语言和框架
    
    前几节的介绍中我们已经有能力制作一个登陆页面,在验证了用户名和密码的正确性后跳转到后台的页面。但是测试后也发现,如果绕过登陆页面。直接输入后台的url地址也可以直接访问的。这个显然是不合理的。其实我们缺失的就是cookie和session配合的验证。有了这个验证过程,我们就可以实现和其他网站一样必须登录才能进入后台页面了。
    
          先说一下这种认证的机制。每当我们使用一款浏览器访问一个登陆页面的时候,一旦我们通过了认证。服务器端就会发送一组随机唯一的字符串(假设是123abc)到浏览器端,这个被存储在浏览端的东西就叫cookie。而服务器端也会自己存储一下用户当前的状态,比如login=true,username=hahaha之类的用户信息。但是这种存储是以字典形式存储的,字典的唯一key就是刚才发给用户的唯一的cookie值。那么如果在服务器端查看session信息的话,理论上就会看到如下样子的字典
    
    {'123abc':{'login':true,'username:hahaha'}}
    
    因为每个cookie都是唯一的,所以我们在电脑上换个浏览器再登陆同一个网站也需要再次验证。那么为什么说我们只是理论上看到这样子的字典呢?因为处于安全性的考虑,其实对于上面那个大字典不光key值123abc是被加密的,value值{'login':true,'username:hahaha'}在服务器端也是一样被加密的。所以我们服务器上就算打开session信息看到的也是类似与以下样子的东西   {'123abc':dasdasdasd1231231da1231231}
    View Code

    Django中的cookie

    Django默认发送的cookie格式为:

    {'csrftoken': 'zPglXV38MGIn3znrQ6JHNhz4UsWZ65SoGInzOnDVYrshlLjVpZz8cpsrlgwxij4p', 'sessionid': 'hb60ns6r1pe8bl805x7wxnsocekz3so5'}

    借用一张别的大神画的图,可以更直观的看出来cookie和session的关系:

    wKioL1bmwJqQWT79AACFVu-rqIs465.gif

       

        知道了原理,我们下面就来用代码实现

    先在templates目录下创建两个html,login.html负责登录页面。index页面代表用户个人首页

    views.py

    from django.shortcuts import render,HttpResponse,redirect
    import datetime
    
    def login(request):
        print("COOKIES",request.COOKIES)
        print("session",request.session)
    
        if request.method =="POST":
            name = request.POST.get("user")
            pwd = request.POST.get("pwd")
            if name =="xiong" and pwd == "123456":
            #     ret = redirect("/index/")
            #     # max_age 和 expires都是设置cookie有效时间,一般情况下两者要设置相同
            #     ret.set_cookie("usernameis","xiongxiong",max_age=8)   #组成键值对
            #     return ret
    
                # cookie +session 写法
                request.session["is_login"] = True
                request.session["user"] = name
                return redirect("/index/")
    
        return render(request,"login.html")
    
    def index(request):
        ## request.COOKIES.get("usernameis", None)  取cookies中键名为usernameis 的值,取不到默认为空,如果不写None 取不到会报错
        # if request.COOKIES.get("usernameis",None) == "xiongxiong":
        #     name = request.COOKIES.get("usernameis",None)
        #     return render(request,"index.html",locals())
    
        if request.session.get("is_login",None):
            print(request.session)
            print(request.session["user"])
            name = request.session.get("user",None)
            return render(request,"index.html",locals())
    
        return redirect("/login/")

    参考视图函数views.py 写法:

    # /usr/bin/env python
    # coding:utf-8
    from django.shortcuts import render
    from django.shortcuts import redirect
    def login(request):
        if request.method=="POST":
            username=request.POST['username']
            pwd=request.POST['passwd']
            if username=='abc' and pwd=='123':
                #设置session内部的字典内容
                request.session['is_login']='true'
                request.session['username']='abc'
                #登录成功就将url重定向到后台的url
                return redirect('/backend/')
        #登录不成功或第一访问就停留在登录页面
        return render(request,'login.html')
    def backend(request):
        """
        这里必须用读取字典的get()方法把is_login的value缺省设置为False,
        当用户访问backend这个url先尝试获取这个浏览器对应的session中的
        is_login的值。如果对方登录成功的话,在login里就已经把is_login
        的值修改为了True,反之这个值就是False的
        """
        is_login=request.session.get('is_login',False)
        #如果为真,就说明用户是正常登陆的
        if is_login:
            #获取字典的内容并传入页面文件
            cookie_content=request.COOKIES
            session_content=request.session
            username=request.session['username']
            return render(request,'backend.html',
                          {
                'cookie_content':cookie_content,
                'session_content':session_content,
                'username':username
                          })
        else:
            """
            如果访问的时候没有携带正确的session,
            就直接被重定向url回login页面
            """
            return redirect('/login/')
    def logout(request):
        """
        直接通过request.session['is_login']回去返回的时候,
        如果is_login对应的value值不存在会导致程序异常。所以
        需要做异常处理
        """
        try:
            #删除is_login对应的value值
            del request.session['is_login']
        except KeyError:
            pass
        #点击注销之后,直接重定向回登录页面
        return redirect('/login/')
    参考yuan先生博客

    login.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>个人首页</title>
    </head>
    <body>
    <form action="/login/" method="post">
        <p>用户名:<input type="text" name="user" placeholder="用户名"></p>
        <p>密码:<input type="text" name="pwd" placeholder="密码"></p>
        <p><input type="submit" value="提交"></p>
    </form>
    </body>
    </html>
    login.html

    index.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>登录页面</title>
    </head>
    <body>
    <h2>登录成功-用户名为:{{ name }}</h2>
    </body>
    </html>
    index.html

    只有在输入了正确的用户名和密码之后才进入到了/backend/页面

    wKiom1bm4UOjEwzlAAE9se9_78U441.png

    从上图中我们看到有一下几点:

    1、login页面正确登录的话,后台页面可以获取到浏览器携带的cookie的。

    2、第一行的sessionid其实就是cookie值

    3、session的内容是加密的,从客户端获取不到session的内容

    4、服务端可以通过预设的key值取出session的内容并打印到前段

    从火狐浏览器里查看cookie

    wKioL1bm5aLicB3pAAC_XkZOUds501.png

    django的session默认是存储在数据库里的,我们再到数据库查看一下真正session内容

    ---> session的工作流程:

    wKiom1bm6EHiV1i0AADUm8yxkhs649.png

    最后我们再来最后的总结一下cookie和session的知识点:

    一、操作Cookie

      获取cookie:request.COOKIES[key]

      设置cookie:response.set_cookie(key,value)

    由于cookie保存在客户端的电脑上,所以,jquery也可以操作cookie。

    <script src='http://830909.blog.51cto.com/static/js/jquery.cookie.js'></script>
    $.cookie("list_pager_num", 30,{ path: '/' });

    二、操作Session(session默认在服务器端保存15天)

      获取session:request.session[key]

      设置session:reqeust.session[key] = value

      删除session:del request.session[key]    

    (这个删除其实就是把数据库的session_data更新为一个其他的值了,并没有立即删除)

    request.session.set_expiry(value)
    * 如果value是个整数,session会在些秒数后失效。
    * 如果value是个datatime或timedelta,session就会在这个时间后失效。
    * 如果value是0,用户关闭浏览器session就会失效。
    * 如果value是None,session会依赖全局session失效策略。

    可以设置失效cookie天数

    ret = redirect("/index/")
            #     # max_age 和 expires都是设置cookie有效时间,一般情况下两者要设置相同
            #     ret.set_cookie("usernameis","xiongxiong",max_age=8)   #usernameis和xiongxiong组成cookies键值对,max_age=8 8秒后cookie失效
                ret.set_cookie("usernameis","xiongxiong",expires=datetime.datetime.utcnow()+datetime.timedelta(days=3))   #组成键值对
  • 相关阅读:
    (一)Python入门-2编程基本概念:18字符串-驻留机制-内存分析-字符串同一判断-值相等判断
    (一)Python入门-2编程基本概念:07内置数据类型-基本算数运算符
    (一)Python入门-2编程基本概念:08整数-不同进制-其他类型转换成整数
    (一)Python入门-2编程基本概念:09浮点数-自动转换-强制转换-增强赋值运算符
    (一)Python入门-2编程基本概念:10时间表示-unix时间点-毫秒和微妙-time模块
    (一)Python入门-2编程基本概念:11布尔值-比较运算符-逻辑运算符及短路问题
    (一)Python入门-2编程基本概念:12同一运算符-整数缓存问题
    (一)Python入门-2编程基本概念:01程序的构成
    (一)Python入门-2编程基本概念:02对象的基本组成和内存示意图
    有关位运算的基础知识总结
  • 原文地址:https://www.cnblogs.com/XJT2018/p/11317857.html
Copyright © 2020-2023  润新知