Day21-Cookie

Posted momo8238

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Day21-Cookie相关的知识,希望对你有一定的参考价值。

1. Cookie,有时也用其复数形式 Cookies,指某些网站为了辨别用户身份、进行 session 跟踪而储存在用户本地终端上的数据(通常经过加密)。例如在某个网站上保存了用户名和密码,3个月内免登陆。如果你换台电脑或者浏览器的话,则需要重新登录。就此说明cookie是保存在客户端浏览器上的一个文件。

 

2.实例---基于cookie实现用户信息验证

当用户名和密码都正确的时候,才跳转到index页面。否则就停留在login.html页面。

 

2.1 在setting中注释掉下面一句,防止报错

 

2.2 在urls.py中写路由对应关系

 

 

2.3 views.py写后端

dic=user_info.get(u) #如果获取到了,表明用户是存在的。

 

 

 

from django.shortcuts import render,HttpResponse,redirect
from django.urls import reverse
# Create your views here.

user_info={
    \'dachengzi\':{\'pwd\':"123123"},
    \'kanbazi\':{\'pwd\':"kkkkkkk"},
}
def login(request):
    if request.method==\'GET\':
        return render(request,\'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,\'login.html\')
        if dic[\'pwd\']==p:
            res=redirect(\'/index/\')
            res.set_cookie(\'username111\',u)
            return res
        else:
            return render(request,\'login.html\')

def index(request):
    #获取当前已经登录的用户名字
    v=request.COOKIES.get(\'username111\')
    if not v:
        return redirect(request,\'/login/\')
    return render(request,\'index.html\',{\'current_user\':v})

 

2.4 写前端 index.html

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

 

2.4 写前端 login.html

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

    </form>
</body>
</html>

 

 

2.5 效果

没有登录之前,是无法访问index页面的。

 

只有先从login页面登录了以后,才能跳转到index页面。

 

 

 

 

3. 在Django里面给cookie提供了一些额外的功能。

request.COOKIES-------表示用户发来数据的时候,它里面带的所携带的所有cookie信息。。。从请求中获取cookie
def cookie(request):
    #用户发来请求时,它里面所携带的所有的cookie信息
    request.COOKIES
    request.COOKIES[\'username111\']
    request.COOKIES.get(\'username111\')

设置cookie 键-值对

response.set_cookie(\'key\',\'value\')
def cookie(request):
    #用户发来请求时,它里面所携带的所有的cookie信息
    request.COOKIES
    request.COOKIES[\'username111\']
    request.COOKIES.get(\'username111\')
response=render(request,\'index.html\') #通过render,redirect把内容返回给浏览器 response=redirect(\'/index/\') #设置cookie,关闭浏览器后就失效
response.set_cookie(\'key\',\'value\') #还可以设置新的cookie 键-值对,也一并返回给浏览器
return response #里面不仅包含了内容,还包含了cookie的键-值对。
 

4. 默认情况下,关闭浏览器后,cookie就失效了,需要重新登录了。通过下面几种方法可以设置失效时间。

    设置用户名和密码的失效时间-方法1,max_age=None


--------res.set_cookie(\'username111\',u,max_age=10)  设置失效时间为10秒


效果:10秒之后,用户名和密码就失效了,从index自动倒退回到login界面,需要重新登录了。




5. 设置用户名和密码的失效时间-方法2,expires=None
import datetime 
current_date=datetime.datetime.utcnow()
current_daate=current_date+datetime.timedelta(seconds=5)
response.set_cookie(\'username111\', "value", expires=current_date)





6. 其它属性
设置cookie的生效路: ---path=\'/\',意思是在所有的url中都生效。path=\'/index\' 指只在index页面有效。
生效的域名: domain=None
https传输: secure=False
  httponly: 只支持http传输,在JS前端是无法获取的,没有安全不安全一说。示例如下:

设置2个cookie,其中1个有httponly=True属性,对比看效果



在页面上访问的时候,看到了2个cookie

 

但是在前端却获取不到

 

7. 增加2个月内免登陆的功能,自己完成。把2个月换算成秒,添加到max_age=XXX里面就可以了。

    注销的本质就是把cookie清除掉。

 

8. 完善实例,基于cookie实现定制显示数据条数

 

8.1----cookie在服务器端能读能写,在客户端也是能读能写的。

8.2----------jQuery有个插件叫jQuery-cookie,通过这个插件可以直接去浏览器上去操作cookie了。

从官网下载插件http://plugins.jquery.com/cookie/

 

 

 

 

 

8.3 用实例来验证,浏览器端确实可以获取到per_page_count这个值。

 

 

 

user_list.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .pagination .page{
            display:inline-block;
            padding:5px;
            background-color:cyan;
            margin:5px;
        }
        .pagination .page.active{
            background-color:brown;
            color:white;
        }
    </style>
</head>
<body>
    <ul>
        {% for item in li %}
            {% include \'li.html\' %}
        {%endfor%}
    </ul>
    <div>
        请选择每页显示条数
        <select id="ps" onchange="changePageSize(this)">
            <option value="10">10</option>
            <option value="30">30</option>
            <option value="50">50</option>
            <option value="100">100</option>
        </select>
    </div>
    <div class="pagination">
        {{page_str}}
    </div>
    <script src="/static/jquery-1.12.4.js"></script>
    <script src="/static/jquery.cookie.js"></script>
    <script>
        function changePageSize(ths){
            var v=$(ths).val();
            console.log(v);
            $.cookie(\'per_page_count\',v);
        }
    </script>
</body>
</html>

 

在Console中也可以看到这个效果。

8.4 服务器端从客户端传过来的cookie中获取到这个值。并且在实例化的时候,把它传递给类。

 

views.py

from django.shortcuts import render,HttpResponse,redirect
from utils import pagination
from django.urls import reverse
# Create your views here.

LIST=[]
for i in range(1000):
    LIST.append(i)

def user_list(request):
    current_page=request.GET.get(\'p\')
    current_page = int(current_page)

    val=request.COOKIES.get(\'per_page_count\')
    print(val)
    val=int(val)

    page_obj=pagination.Page(current_page,len(LIST),val)
    data=LIST[page_obj.start:page_obj.end]
    page_str=page_obj.page_str("/user_list/")
    return render(request,\'user_list.html\',{\'data\':data,\'page_str\':page_str})

user_info = {
    \'dachengzi\': {\'pwd\': "123123"},
    \'kanbazi\': {\'pwd\': "kkkkkkk"},
}

def login(request):
    if request.method == \'GET\':
        return render(request, \'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, \'login.html\')

        if dic[\'pwd\'] == p:
            res = redirect(\'/index/\')
            res.set_cookie(\'username111\', u)
            return res
        else:
            return render(request, \'login.html\')

def index(request):
    # 获取当前已经登录的用户名字
    v = request.COOKIES.get(\'username111\')
    if not v:
        return redirect(request, \'/login/\')
    return render(request, \'index.html\', {\'current_user\': v})

 

8.5 完善功能。用户选中每页显示多少条,浏览器上就显示多少条。

 

代码修改如下:

 

 

 

8.6 完善功能,指定生效的url路径

var v=$.cookie(\'per_page_count\',{\'path\':"/user_list/"}); 指定路径


9. 至此,程序粘贴如下:

urls.py

 

from django.conf.urls import url
from django.contrib import admin
from app_ch import views

urlpatterns = [
    url(r\'^admin/\', admin.site.urls),
    url(r\'^user_list/$\', views.user_list),
    url(r\'^login\', views.login),
    url(r\'^index\', views.index),
]

 

 views.py

from django.shortcuts import render,HttpResponse,redirect
from utils import pagination
from django.urls import reverse
# Create your views here.

LIST=[]
for i in range(1000):
    LIST.append(i)

def user_list(request):
    current_page=request.GET.get(\'p\')
    current_page = int(current_page)

    val=request.COOKIES.get(\'per_page_count\')
    print(val)
    val=int(val)

    page_obj=pagination.Page(current_page,len(LIST),val)
    data=LIST[page_obj.start:page_obj.end]
    page_str=page_obj.page_str("/user_list/")
    return render(request,\'user_list.html\',{\'data\':data,\'page_str\':page_str})

user_info = {
    \'dachengzi\': {\'pwd\': "123123"},
    \'kanbazi\': {\'pwd\': "kkkkkkk"},
}

def login(request):
    if request.method == \'GET\':
        return render(request, \'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, \'login.html\')

        if dic[\'pwd\'] == p:
            res = redirect(\'/index/\')
            res.set_cookie(\'username111\', u)
            return res
        else:
            return render(request, \'login.html\')

def index(request):
    # 获取当前已经登录的用户名字
    v = request.COOKIES.get(\'username111\')
    if not v:
        return redirect(request, \'/login/\')
    return render(request, \'index.html\', {\'current_user\': v})

 pagination.py

from django.utils.safestring import mark_safe
class Page:
    def __init__(self,current_page,data_count,per_page_count=10,pager_num=7):
        self.current_page=current_page
        self.data_count=data_count
        self.per_page_count=per_page_count
        self.pager_num=pager_num
    @property
    def start(self):
        return (self.current_page - 1) * self.per_page_count

    @property
    def end(self):
        return self.current_page*self.per_page_count

    @property
    def total_count(self):
        v, y = divmod(self.data_count,self.per_page_count)
        if y:
            v = v+ 1
        return v

    def page_str(self,base_url):
        page_list = []
        if self.total_count < self.pager_num:
            start_index = 1
            end_index = self.total_count + 1
        else:
            if self.current_page <= (self.pager_num + 1) / 2:
                start_index = 1
                end_index = self.pager_num + 1
            else:
                start_index = self.current_page - (self.pager_num - 1) / 2
                end_index = self.current_page + (self.pager_num + 1) / 2
                if (self.current_page + (self.pager_num - 1) / 2) > self.total_count:
                    end_index = self.total_count + 1
                    start_index = self.total_count - self.pager_num + 1

        if self.current_page == 1:
            prev = \'<a class="page" href="javascript:void(0)">上一页</a>\'
        else:
            prev = \'<a class="page" href="%s?p=%s">上一页</a>\' % (base_url,self.current_page - 1)
        page_list.append(prev)

        for i in range(int(start_index), int(end_index)):
            if i == self.current_page:
                temp = \'<a class="page active" href="%s?p=%s">%s</a>\' % (base_url,i, i)
            else:
                temp = \'<a class="page" href="%s?p=%s">%s</a>\' % (base_url,i, i)
            page_list.append(temp)

        if self.current_page == self.total_count:
            nex = \'<a class="page" href="javascript:void(0);">下一页</a>\'
        else:
            nex = \'<a class="page" href=%s?p=%s>下一页</a>\' % (base_url,self.current_page + 1)
        page_list.append(nex)

        jump = \'\'\'
            <input type=\'text\'/><a onclick=\'jumpTo(this,"%s?p=");\'>Go</a>
            <script>
                function jumpTo(ths,base){
                    var val=ths.previousSibling.value;
                    location.href=base+val;
                }
            </script>
        \'\'\'%(base_url)

        page_list.append(jump)
        page_str = mark_safe("".join(page_list))
        return page_str

 user_list.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .pagination .page{
            display:inline-block;
            padding:5px;
            background-color:cyan;
            margin:5px;
        }
        .pagination .page.active{
            background-color:brown;
            color:white;
        }
    </style>
</head>
<body>
    <ul>
        {% for i in data%}
            <li>{{i}}</li>
        {% endfor %}
    </ul>
    <div>
        选择每页显示的条数:
        <select id="ps" onchange="changePageSize(this)">
            <option value="10">10</option>
            <option value="30">30</option>
            <option value="50">50</option>
        </select>
    </div>
    <div class="pagination">
        {{page_str}}
    </div>
    <script src="/static/jquery-1.12.4.js"></script>
    <script src="/static/jquery.cookie.js"></script>
    <script>
        $(function(){
            var v=$.cookie(\'per_page_count\',{\'path\':"/user_list/"});
            $(\'#ps\').val(v);
        });
        function changePageSize(ths){
            var v=$(ths).val();
            $.cookie(\'per_page_count\',v,{\'path\':"/user_list/"});
            location.reload();
        }
    </script>
</body>
</html>

 

login.html

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

 

index.html

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

 

 

 10. 带签名的cookie

-------明文:

获取cookie: request.COOKIES.get(\'......\')

设置cookie: response.set_cookie(.....)

--------密文:

加密解密如下,注意盐要对应,否则解密会不成功。

obj=HttpResponse(\'s\')  #返回给客户端的数据
obj.set_signed_cookie(\'username\',"kangbazi",salt=\'XXX\') 通过XXX这个字符串,对cookie的内容进行加密。
request.get_signed_cookie(\'username\',salt="XXX") 服务器端获取得时候,需要解密。



11. 用装饰器实现用户验证
假设这里不仅有index页面需要验证,然后还有一个order页面也需要验证。我们尝试用装饰器来实现。


新建1个order页面,用FBV装饰器来实现。




用另外一种方法CBV实现



现在还没有登录,尝试用get访问的时候,效果如下:




在dispatch方法执行完了以后,才执行下面的方法。

from django.shortcuts import render,HttpResponse,redirect
from utils import pagination
from django.urls import reverse
# Create your views here.

LIST=[]
for i in range(1000):
    LIST.append(i)

def user_list(request):
    current_page=request.GET.get(\'p\')
    current_page = int(current_page)

    val=request.COOKIES.get(\'per_page_count\')
    print(val)
    val=int(val)

    page_obj=pagination.Page(current_page,len(LIST),val)
    data=LIST[page_obj.start:page_obj.end]
    page_str=page_obj.page_str("/user_list/")
    return render(request,\'user_list.html\',{\'data\':data,\'page_str\':page_str})

user_info = {
    \'dachengzi\': {\'pwd\': "123123"},
    \'kanbazi\': {\'pwd\': "kkkkkkk"},
}

def login(request):
    if request.method == \'GET\':
        return render(request, \'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, \'login.html\')

        if dic[\'pwd\'] == p:
            res = redirect(\'/index/\')
            res.set_cookie(\'username111\', u)
            return res
        else:
            return render(request, \'login.html\')

def auth(func):
    def inner(request,*args,**kwargs):
        v = request.COOKIES.get(\'username111\')
        if not v:
            return redirect(request, \'/login/\')
        return func(request,*args,**kwargs)
    return inner

@auth
def index(request):
    # 获取当前已经登录的用户名字
    v = request.COOKIES.get(\'username111\')
    return render(request, \'index.html\', {\'current_user\': v})

from django import views
from django.utils.decorators import method_decorator
class Order(views.View):
    @method_decorator(auth)
    def dispatch(self,request,*args,**kwargs):
        return super(Order,self).dispatch(request,*args,**kwargs)

    def get(self,request):
        v = request.COOKIES.get(\'username111\')
        return render(request, \'index.html\', {\'current_user\': v})
    
    def post(self,request):
        v = request.COOKIES.get(\'username111\')
        return render(request, \'index.html\', {\'current_user\': v})

def order(request):
    # 获取当前已经登录的用户名字
    v = request.COOKIES.get(\'username111\')
    return render(request, \'index.html\', {\'current_user\': v})

 

可以更优化,把装饰器写到类的上面。



FBV和CBV两种方法实现装饰器的比较




至此程序如下:

urls.py
from django.conf.urls import url
from django.contrib import admin
from app_ch import views

urlpatterns = [
    url(r\'^admin/\', admin.site.urls),
    url(r\'^user_list/$\', views.user_list),
    url(r\'^login\', views.login),
    url(r\'^index\', views.index),
    url(r\'^order\', views.Order.as_view()),
]

views.py
from django.shortcuts import render,HttpResponse,redirect
from utils import pagination
from django.urls import reverse
# Create your views here.

LIST=[]
for i in range(1000):
    LIST.append(i)

def user_list(request):
    current_page=request.GET.get(\'p\')
    current_page = int(current_page)

    val=request.COOKIES.get(\'per_page_count\')
    print(val)
    val=int(val)

    page_obj=pagination.Page(current_page,len(LIST),val)
    data=LIST[page_obj.start:page_obj.end]
    page_str=page_obj.page_str("/user_list/")
    return render(request,\'user_list.html\',{\'data\':data,\'page_str\':page_str})

user_info = {
    \'dachengzi\': {\'pwd\': "123123"},
    \'kanbazi\': {\'pwd\': "kkkkkkk"},
}

def login(request):
    if request.method == \'GET\':
        return render(request, \'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, \'login.html\')

        if dic[\'pwd\'] == p:
            res = redirect(\'/index/\')
            res.set_cookie(\'username111\', u)
            return res
        else:
            return render(request, \'login.html\')

def auth(func):
    def inner(request,*args,**kwargs):
        v = request.COOKIES.get(\'username111\')
        if not v:
            return redirect(request, \'/login/\')
        return func(request,*args,**kwargs)
    return inner

@auth
def index(request):
    # 获取当前已经登录的用户名字
    v = request.COOKIES.get(\'username111\')
    return render(request, \'index.html\', {\'current_user\': v})

from django import views
from django.utils.decorators import method_decorator

@method_decorator(auth,name=\'dispatch\')
class Order(views.View):
    def get(self,request):
        v = request.COOKIES.get(\'username111\')
        return render(request, \'index.html\', {\'current_user\': v})

    def post(self,request):
        v = request.COOKIES.get(\'username111\')
        return render(request, \'index.html\', {\'current_user\': v})

def order(request):
    # 获取当前已经登录的用户名字
    v = request.COOKIES.get(\'username111\')
    return render(request, \'index.html\', {\'current_user\': v})

 utils-->pagination.py

from django.utils.safestring import mark_safe
class Page:
    def __init__(self,current_page,data_count,per_page_count=10,pager_num=7):
        self.current_page=current_page
        self.data_count=data_count
        self.per_page_count=per_page_count
        self.pager_num=pager_num
    @property
    def start(self):
        return (self.current_page - 1) * self.per_page_count

    @property
    def end(self):
        return self.current_page*self.per_page_count

    @property
    def total_count(self):
        v, y = divmod(self.data_count,self.per_page_count)
        if y:
            v = v+ 1
        return v

    def page_str(self,base_url):
        page_list = []
        if self.total_count < self.pager_num:
            start_index = 1
            end_index = self.total_count + 1
        else:
            if self.current_page <= (self.pager_num + 1) / 2:
                start_index = 1
                end_index = self.pager_num + 1
            else:
                start_index = self.current_page - (self.pager_num - 1) / 2
                end_index = self.current_page + (self.pager_num + 1) / 2
                if (self.current_page + (self.pager_num - 1) / 2) > self.total_count:
                    end_index = self.total_count + 1
                    start_index = self.total_count - self.pager_num + 1

        if self.current_page == 1:
            prev = \'<a class="page" href="javascript:void(0)">上一页</a>\'
        else:
            prev = \'<a class="page" href="%s?p=%s">上一页</a>\' % (base_url,self.current_page - 1)
        page_list.append(prev)

        for i in range(int(start_index), int(end_index)):
            if i == self.current_page:
                temp = \'<a class="page active" href="%s?p=%s">%s</a>\' % (base_url,i, i)
            else:
                temp = \'<a class="page" href="%s?p=%s">%s</a>\' % (base_url,i, i)
            page_list.append(temp)

        if self.current_page == self.total_count:
            nex = \'<a class="page" href="javascript:void(0);">下一页</a>\'
        else:
            nex = \'<a class="page" href=%s?p=%s>下一页</a>\' % (base_url,self.current_page + 1)
        page_list.append(nex)

        jump = \'\'\'
            <input type=\'text\'/><a onclick=\'jumpTo(this,"%s?p=");\'>Go</a>
            <script>
                function jumpTo(ths,base){
                    var val=ths.previousSibling.value;
                    location.href=base+val;
                }
            </script>
        \'\'\'%(base_url)

        page_list.append(jump)
        page_str = mark_safe("".join(page_list))
        return page_str

 

login.html

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

 

index.html

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

 


 




 

以上是关于Day21-Cookie的主要内容,如果未能解决你的问题,请参考以下文章

sqli-labs less21 Cookie Injection- Error Based- complex - string ( 基于错误的复杂的字符型Cookie注入)

[code] PTA 胡凡算法笔记 DAY039

list(), if 和短路评估

DAY9-字符串笔记整理2018-1-19

微信小程序代码片段

VSCode自定义代码片段——CSS选择器