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 ------

posted @ 2018-03-01 17:36  王先生是胖子  阅读(207)  评论(0编辑  收藏  举报