• Django之Cookie


    Cookie是保存在用户浏览器端的一个键值对。

      Cookie是存在用户浏览器端的。保存用户登录的凭证。 

      服务端可以向用户浏览器端写Cookie。 

      客户端每次发请求时,会携带Cookie去。

        Cookie 的发送是放在请求头里的数据。(request.Cookies) 

      在响应头里,也是有Cookie的。是set_Cookie。

      在Cookie的应用中,有比如在浏览器登录一次,就会记住密码,下次在登录时,就不用再输出密码,密码是自动填充直接登录,这也是Cookie在做的。

    实现主页面在没有登录状态下,要强制登录的功能。

      要在主页面的函数中,先进行Cookie的认证。

      要先去请求的Cookie中找凭证。   

    #去Cookie中get拿取值
    tk = request.COOKIES.get("ticket")
    #对拿到的tk进行判断,如果是tk没有值,为None的话,就要去用户登录。
    if not tk:
        return redirect("/login/")
    def classes(request):
        """
        链接数据库
        :param request: 用户请求的相关的所有信息(对象)
        :return:
        """
        # 去Cookie中get拿取值
        tk = request.COOKIES.get("ticket")
        # 对拿到的tk进行判断,如果是tk没有值,为None的话,就要去用户登录。
        if not tk:
            return redirect("/login/")
       else:
          conn = pymysql.connect(host="127.0.0.1",port=3306,user='root',passwd='redhat',db='weibo',charset='utf8')
          cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) #改为字典
          cursor.execute("select nid,title from classes")
          class_list = cursor.fetchall()
          cursor.close()
          conn.close()
        return render(request, "classes.html",{"class_lsit":class_list})

       在login的函数中:

    def login(request):
        """
        处理用户请求,并返回内容
        :param request: 用户请求的相关的所有信息(对象)
        :return:
        """
        #通过请求方式,返回不同的信息
        if request.method == "GET":
            return render(request,"login.html")
        else:
            print(request.POST) #用户POST提交的数据,(请求体里的数据)
            username = request.POST.get("username") #取出字典里的数据。
            password = request.POST.get("password")  #取出字典里的数据。
            if username == "yanyan" and password == "1314":
                # 可以用 redirect 重定向,跳转到指定页面。
                obj =  redirect("/index/")
                #给浏览器回写Cookie,这是请求的Cookie
                obj.set_cookie("ticket","aaaaa")
                return obj
            else:
                #登录失败
                return render(request,"login.html",{"msg":"username or password is error"})

       响应头的Cookie:

    def test(request):
        #响应返回的数据
        obj = HttpResponse("OK")
        #返回给用户的Cookie,在响应头中体现。
        obj.set_cookie("k1":"v1")
        return obj

     Cookie设置超时时间:

      set_cookie("ticket","asd",max_age=10 )

        max_age是设置超时时间的。单位是秒。

        expires也是设置超时时间的,是设置具体的超时日期的。

    def login(request):
        if request.method == "GET":
            return render(request,"login.html")
        else:
            htmlusername = request.POST.get("username")
            htmlpassword = request.POST.get("password")
            userinfo_list = sqlheper.get_list("select username,password from userinfo where username = %s",[htmlusername,])
            for item in userinfo_list:
                print(item["username"],item["password"])
            if len(htmlpassword)>0:
                if htmlusername == item["username"] and htmlpassword == item["password"]:
                    obj = redirect("/index/")
                    ct = datetime.datetime.utcnow()
                    #设置当前时间
                    v = timedelta(seconds=10)
                    #时间的加减用timedelta 来操作
                    value = ct+v
                    obj.set_cookie("ticket","yanzheng",max_age=10)
                    obj.set_cookie("ticket","yanzheng",expires=value)    //这里的yanzheng是明文的
                    return obj
                else:
                    return render(request,"login.html",{"msg":"username or password is error"})
            else:
                return render(request, "login.html", {"msg": "password 不能为空"})

    Cookie 的path应用:

      path是用来指定Cookie可以读取的url。比如有两个函数,分别设置不同的Cookie值,这时在指定path,那么在执行那个函数的时候,Cookie就不会拿取所有,而是只去拿取path指定的值。

    def test1(request):
        print(request.COOKIES)
        obj = HttpResponse("OK")
        obj.set_cookie("k2","v2",path="/test1")
        return obj
    
    def test2(request):
        print(request.COOKIES)
        #拿取所有的Cookie值
        obj = HttpResponse("ok")
        return obj

    Cookie 的 domain :

      domain 是设置在访问某域名的时候才会获取的Cookie值。

      一般只有在写SSO后者是统一认证登录时,会涉及到多域名时,才会设置domain。

    Cookie 的 httponly :

      httponly 是做安全相关的事情。httponly表示定义的Cookie只能通过http来发送请求。

      如果把Cookie写到用户的浏览器端,用户是可以获取你的Cookie并操作的。但是,如果把httponly的值写成True的话,用户在浏览器端是找不到Cookie的,并且没有权限去操作这个Cookie。因为它只给http请求发送请求时应用,所以只能自http请求中传入,js代码无法获取。但可以通过抓包来拿取。

    Cookie 的 secure:  

      secure 是给https提供的功能。 如果需要secure提供服务,比如做网站相关,要将值改为True。

    Cookie 的 扩展签名:

      签名就是将我们明文的Cookie值进行一个加密操作。

        obj.set_signed_cookie() 就是可以设置签名的Cookie。而这里主要的参数就salt。salt的值就是签名,也可以理解为加密的值。而在接受端,也不再是request.COOKIES.get("ticket") 啦,而是request.get_signed_cookie("ticket",salt="Code Cookie"),因为在Cookie的发送端的login函数里,是我们自己加密的,所以在接收端这么classes函数就是自己解密。

      views.py 中login发送Cookie的函数的示例:

    def login(request):
        if request.method == "GET":
            return render(request,"login.html")
        else:
            htmlusername = request.POST.get("username")
            htmlpassword = request.POST.get("password")
            userinfo_list = sqlheper.get_list("select username,password from userinfo where username = %s",[htmlusername,])
            for item in userinfo_list:
                print(item["username"],item["password"])
            if len(htmlpassword)>0:
                if htmlusername == item["username"] and htmlpassword == item["password"]:
                    obj = redirect("/index/")
                    # obj.set_cookie("ticket","yanzheng",max_age=10)
                    obj.set_signed_cookie("ticket","Cookie",salt="Code Cookie",max_age=10) #这里就设置了salt
                    return obj
                else:
                    return render(request,"login.html",{"msg":"username or password is error"})
            else:
                return render(request, "login.html", {"msg": "password 不能为空"})

      views.py 中classes或index接受Cookie的函数的示例:

    def classes(request):
        tk = request.get_signed_cookie("ticket",salt="Code Cookie")   #接受Cookie的方式
        print("classes",tk)
        if not tk:
            return redirect("/login/")
        else:
            conn = pymysql.connect(host="127.0.0.1",port=3306,user='root',passwd='redhat',db='weibo',charset='utf8')
            cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) #改为字典
            cursor.execute("select nid,title from classes")
            class_list = cursor.fetchall()
            cursor.close()
            conn.close()
            return render(request, "classes.html",{"class_lsit":class_list})

      在前端查看ticket的状态:

    Cookie 自己定义签名的规则: 

      使加密规则文件生效,就在settings中加上自己写的签名规则的类。

      因为在源码里,这个规则是默认用的类是TimestampSigner的方法。

      创建一个py文件,名change.py:

    from django.core.signing import TimestampSigner
    class MySigner(TimestampSigner):
        def sign(self, value):
            """
            加密
            :param value: 加密的方式就是在值的后面加123,
            :return: 
            """
            return value + '123'
        def unsign(self, value, max_age=None):
            """
            解密
            :param value: 
            :param max_age: 
            :return: 
            """
            v = value[0:-3]   #这里解密的值的取值之取到Cookie,所以后端的值,只能拿到Cookie,那个加密的123是拿不到的。
            return v

      在Django的Settings配置文件中,添加:

    SIGNING_BACKEND = 'change.MySigner'  #这样就指定了自己的加密方式
    
    xxx为MySigner的文件路径。

      结果展示:

     ------ END ------

  • 相关阅读:
    二,数据类型与流程控制语句
    一,cmd指令集与变量
    web第九天,浮动与定位
    web第八天,PS切图与float浮动
    web第七天,标签分类
    web第六天,CSS优先级与盒子模型
    web第五天复合样式与选择器
    web第四天,CSS基础
    web第三天 表单与css基础
    装饰器
  • 原文地址:https://www.cnblogs.com/george92/p/8489619.html
Copyright © 2020-2023  润新知