zoukankan      html  css  js  c++  java
  • Djang之cookie与session

    一、cookie

    1、cookie概述

    Cookie的由来
    大家都知道HTTP协议是无状态的。
    无状态的意思是每次请求都是独立的,它的执行情况和结果与前面的请求和之后的请求都无直接关系,它不
    会受前面的请求响应情况直接影响,也不会直接影响后面的请求响应情况。
    一句有意思的话来描述就是人生只如初见,对服务器来说,每次的请求都是全新的。
    状态可以理解为客户端和服务器在某次会话中产生的数据,那无状态的就以为这些数据不会被保留。会话中
    产生的数据又是我们需要保存的,也就是说要“保持状态”。因此Cookie就是在这样一个场景下诞生。
    
    
    什么是Cookie
    Cookie具体指的是一段小信息,它是服务器发送出来存储在浏览器上的一组组键值对,下次访问服务器时浏
    览器会自动携带这些键值对,以便服务器提取有用信息。
    
    
    Cookie的原理
    cookie的工作原理是:由服务器产生内容,浏览器收到请求后保存在本地;当浏览器再次访问时,浏览器会
    自动带上Cookie,这样服务器就能通过Cookie的内容来判断这个是“谁”了。


    查看cookie

    image


    2、Django中操作Cookie

    设置Cookie
    rep = HttpResponse(...)
    rep = render(request, ...)
    
    rep.set_cookie(key,value,...)
    rep.set_signed_cookie(key,value,salt='加密盐', max_age=None, ...)
    
    
    # 参数:
      # key, 键
      # value='', 值
      # max_age=None, 超时时间(只能用于除IE以外的浏览器)
      # expires=None, 超时时间(可兼容于IE)
      # path='/', Cookie生效的路径,/ 表示根路径,特殊的:根路径的cookie可以被任何url的页面访问
      # domain=None, Cookie生效的域名
      # secure=False, https传输
      # httponly=False 只能http协议传输,无法被JavaScript获取(不是绝对,底层抓包可以获取到也可以被覆盖)


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


    删除Cookie
    def logout(request):
        rep = redirect("/login/")
        rep.delete_cookie("user")  # 删除用户浏览器上之前设置的usercookie值
        return rep


    3、Cookie版登陆校验

    urls.py

    from django.conf.urls import url
    from django.contrib import admin
    from app01 import views
    
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^reg/', views.reg),
        url(r'^login/', views.login),
        url(r'^index/', views.index),
        url(r'^home/', views.home),
        url(r'^xxx/', views.xxx),
    ]


    views.py

    def login(request):
        if request.method == 'POST':
            username = request.POST.get('username')
            password = request.POST.get('password')
            if username == 'jason' and password == '123':
                # 用户可能访问了一个页面,但是没登录,就让他去登录了
                # 登陆完以后,还让他重新回到他上次想访问的页面
                # 拿到用户上次想访问的页面(装饰器里设置的next)
                old_path = request.GET.get('next')
                # 如果old_path有值,就让他跳过去
                if old_path:
                    obj = redirect(old_path)
                # 如果old_path没值,就让跳到home
                else:
                    obj = redirect('/home/')
                # 用户登录成功 往浏览器设置一个cookie键值对
                # expires(可兼容IE):cookie超时时间,这里写的是一周
                # 除了IE,其他浏览器也可用 max_age 参数
                obj.set_cookie('name', 'jason', expires=7*24*3600)
                return obj
        return render(request, 'login.html')
    
    
    from functools import wraps
    # 可能有很多页面,就装饰器帮我干跳转到登录页面的活
    def login_auth(func):
        @wraps(func)
        def inner(request, *args, **kwargs):
            # 校验cookie
            # 没跳转之前,先拿到第一次访问的页面
            old_path = request.get_full_path()
            if request.COOKIES.get('name'):
                return func(request, *args, **kwargs)
            return redirect('/login/?next=%s' % old_path)
        return inner
    
    
    @login_auth
    def index(request):
        return HttpResponse('index页面,只有登录才能看')
    
    
    @login_auth
    def home(request):
        return HttpResponse('home页面,只有登录才能看')
    
    
    @login_auth
    def xxx(request):
        return HttpResponse('xxx页面,只有登录才能看')


    login.html

    <body>
    <form method="post">
        <p>username:<input type="text" name="username"></p>
        <p>password:<input type="text" name="password"></p>
        <input type="submit">
    </form>
    </body>


    二、session

    1、session概述

    Session的由来
    Cookie虽然在一定程度上解决了“保持状态”的需求,但是由于Cookie本身最大支持4096字节,以及Cookie本
    身保存在客户端,可能被拦截或窃取,因此就需要有一种新的东西,它能支持更多的字节,并且他保存在服
    务器,有较高的安全性。这就是Session。
    
    问题来了,基于HTTP协议的无状态特征,服务器根本就不知道访问者是“谁”。那么上述的Cookie就起到桥接
    的作用。
    
    我们可以给每个客户端的Cookie分配一个唯一的id,这样用户在访问时,通过Cookie,服务器就知道来的人
    是“谁”。然后我们再根据不同的Cookie的id,在服务器上保存一段时间的私密资料,如“账号密码”等等。
    
    总结而言:Cookie弥补了HTTP无状态的不足,让服务器知道来的人是“谁”;但是Cookie以文本的形式保存在
    本地,自身安全性较差;所以我们就通过Cookie识别不同的用户,对应的在Session里保存私密的信息以及超
    过4096字节的文本。
    
    另外,上述所说的Cookie和Session其实是共通性的东西,不限于语言和框架。


    2、Django中Session相关方法

    # 获取、设置、删除Session中数据
    request.session['k1']
    request.session.get('k1',None)
    request.session['k1'] = 123
    request.session.setdefault('k1',123) # 存在则不设置
    del request.session['k1']
    
    
    # 所有 键、值、键值对
    request.session.keys()
    request.session.values()
    request.session.items()
    request.session.iterkeys()
    request.session.itervalues()
    request.session.iteritems()
    
    # 会话session的key
    request.session.session_key
    
    # 将所有Session失效日期小于当前日期的数据删除
    request.session.clear_expired()
    
    # 检查会话session的key在数据库中是否存在
    request.session.exists("session_key")
    
    # 删除当前会话的所有Session数据
    request.session.delete()
      
    # 删除当前的会话数据并删除会话的Cookie。
    request.session.flush() 
        这用于确保前面的会话数据不可以再次被用户的浏览器访问
        例如,django.contrib.auth.logout() 函数中就会调用它。
    
    # 设置会话Session和Cookie的超时时间
    request.session.set_expiry(value)
        * 如果value是个整数,session会在些秒数后失效。
        * 如果value是个datatime或timedelta,session就会在这个时间后失效。
        * 如果value是0,用户关闭浏览器session就会失效。
        * 如果value是None,session会依赖全局session失效策略。


    # django默认的session存活时间是两周(14天)
    
    # 设置session
        request.session['name'] = 'jason'
        # 1.先生成一个随机的字符串
        # 2.在django session表中存储该随机字符串与数据的记录(一个浏览器一行)
        # 3.将随机的字符串发送给客户端浏览器
        
    # 获取session
        request.session.get('name')
        # 1.django自动获取浏览器随机字符串取django session表里面比对
        # 2.如果比对成功 会将当前随机字符串对应的数据赋值给request.session
        # 3.通过request.session操作该数据(数据不存在也不会影响我们的业务逻辑)
    
    # 删除session
        # 删除当前会话的所有Session数据(删除数据库的)
        request.session.delete()
      
        # 删除当前的会话数据并删除会话的Cookie(删除数据库和浏览器的)
        request.session.flush() 
        这用于确保前面的会话数据不可以再次被用户的浏览器访问
        例如,django.contrib.auth.logout() 函数中就会调用它。
    
    # 设置会话Session和Cookie的超时时间
        request.session.set_expiry(value)
        * 如果value是个整数,session会在些秒数后失效。
        * 如果value是个datatime或timedelta,session就会在这个时间后失效。
        * 如果value是0,用户关闭浏览器session就会失效。
        * 如果value是None,session会依赖全局session失效策略。
    # 设置session
    def set_session(request):
        request.session['name'] = 'jason'
        # 可以设置多个,但在数据库中也是存一条(一个浏览器一条),
        request.session['name1'] = 'egon'
        request.session['name2'] = 'tank'
        return HttpResponse('set_ok')
    
    
    # 获取session
    def get_session(request):
        print(request.session.get('name'))
        print(request.session.get('name1'))
        print(request.session.get('name2'))
        return HttpResponse('get_ok')
    
    
    # 删除session
    def del_session(request):
        request.session.delete()
        return HttpResponse('del_ok')
    
    
    def flush_session(request):
        request.session.flush()
        return HttpResponse('flush_ok')


    3、session流程解析

    image


    4、CBV加装饰器实现登录验证

    urls.py

    from django.conf.urls import url
    from django.contrib import admin
    from app01 import views
    
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^login/', views.login),
        url(r'^home/', views.MyHome.as_view()),
    ]


    views.py

    from django.shortcuts import render, HttpResponse, redirect
    from django.views import View
    from functools import wraps
    
    # 给CBV加装饰器,需要导入以下模块
    from django.utils.decorators import method_decorator
    
    # Create your views here.
    def login(request):
        if request.method == 'POST':
            username = request.POST.get('username')
            pwd = request.POST.get('pwd')
            if username == 'jason' and pwd == '123':
                request.session['name'] = 'jason'
                return redirect('/home/')
        return render(request, 'login.html')
    
    
    def login_auth(func):
        @wraps(func)
        def inner(request, *args, **kwargs):
            if request.session.get('name'):
                return func(request, *args, **kwargs)
            return redirect('/login/')
        return inner
    
    
    # 第二种加装饰器的方法,@method_decorator(装饰器名字,name='给某个方法加')
    # @method_decorator(login_auth, name='get')
    class MyHome(View):
        # 第三种加装饰器的方法,该类里的方法都会被装饰
        @method_decorator(login_auth)
        def dispatch(self, request, *args, **kwargs):
            super().dispatch(request, *args, **kwargs)
    
        # 第一种加装饰器的方法,@method_decorator(装饰器名字)
        # @method_decorator(login_auth)
        def get(self, request):
            """
            处理get请求
            """
            return HttpResponse('get')
    
        def post(self, request):
            """
            处理post请求
            """
            return HttpResponse('post')
    
    
    # ----------------------------
    # 在CBV中使用装饰器,上面代码中已经体现出来了,有三种方式,总结一下:
        # 先导包:from django.utils.decorators import method_decorator
        # 方式一,加在某个具体的方法上,格式:@method_decorator(装饰器名字)
        # 方式二,加在类上,格式:@method_decorator(装饰器名字,name='给某个方法加')
        # 方式三,写一个dispatch方法,加在其上,该类里的方法都会被装饰,格式:@method_decorator(login_auth)


    login.html

    <body>
    <form action="" method="post">
        <p>username: <input type="text" name="username"></p>
        <p>password: <input type="text" name="pwd"></p>
        <input type="submit">
    </form>
    </body>
  • 相关阅读:
    python 并发编程 多线程 event
    python 并发编程 多线程 定时器
    python 并发编程 多线程 信号量
    linux top 查看CPU命令
    python 并发编程 多线程 GIL与多线程
    python 并发编程 多线程 死锁现象与递归锁
    python 并发编程 多线程 GIL与Lock
    python GIL全局解释器锁与互斥锁 目录
    python 并发编程 多线程 GIL全局解释器锁基本概念
    执行python程序 出现三部曲
  • 原文地址:https://www.cnblogs.com/weiyiming007/p/12401218.html
Copyright © 2011-2022 走看看