• Cookie 和 Session


    1. Cookie是什么
      保存在浏览器端的键值对

    2.为什么要有Cookie?
      因为HTTP请求是无状态的

    3.Cookie的原理?
      服务端可以在返回响应的时候 做手脚
      在浏览器上写入键值对(Cookie)
      浏览器发送请求的时候会自动携带该网站保存在我浏览器的键值对(Cookie)

    4.Django 从请求携带的Cookie中取值:

    request.COOKIES['key']
    request.get_signed_cookie(key, default=RAISE_ERROR, salt='', max_age=None)

    参数:

    • key, 键
    • value='', 值
    • max_age=None, 超时时间
    • expires=None, 超时时间(IE requires expires, so set it if hasn't been already.)
    • path='/', Cookie生效的路径,/ 表示根路径,特殊的:根路径的cookie可以被任何url的页面访问
    • domain=None, Cookie生效的域名
    • secure=False, https传输
    • httponly=False 只能http协议传输,无法被JavaScript获取(不是绝对,底层抓包可以获取到也可以被覆盖)


    5.Django中设置Cookie:(针对的是响应对象)

    rep = HttpResponse(...)
    render(request, "xxx.html)
    redirect()
    rep.set_cookie(key,value,...)
    rep.set_signed_cookie(key, value, salt="加密盐", max_age=7)

    cookie版本的登录

    from django.shortcuts import render, redirect
    
    # Create your views here.
    from functools import wraps
    
    
    def check_login(func):
        @wraps(func)  # 装饰器修复技术
        def inner(request, *args, **kwargs):
            ret = request.get_signed_cookie("is_login", default="0", salt="s10nb")
            if ret == "1":
                # 已经登陆过的 继续执行
                return func(request, *args, **kwargs)
            # 没有登录过的 跳转到登录页面
            else:
                # 获取当前访问的URL
                next_url = request.path_info
                print(next_url)
                return redirect("/login/?next={}".format(next_url))
        return inner
    
    
    def login(request):
        print(request.get_full_path())  # 获取当前请求的路径和参数
        print(request.path_info)  # 取当前请求的路径
        print("-" * 120)
    
        if request.method == "POST":
            user = request.POST.get("user")
            pwd = request.POST.get("pwd")
            # 从URL里面取到 next 参数
            next_url = request.GET.get("next")
    
            if user == "alex" and pwd == "dsb":
                # 登陆成功
                # 告诉浏览器保存一个键值对
    
                if next_url:
                    rep = redirect(next_url)  # 得到一个响应对象
                else:
                    rep = redirect("/home/")  # 得到一个响应对象
    
                # rep.set_cookie("is_login", "1")
                # 设置加盐的cookie
                rep.set_signed_cookie("is_login", "1", salt="s10nb", max_age=10)  # 单位是秒
                return rep
    
        return render(request, "login.html")
    
    
    def home(request):
        # 从请求的cookie中找 有没有 xiaohei
        # ret = request.COOKIES.get("is_login", 0)
        # 取加盐过的
        ret = request.get_signed_cookie("is_login", default="0", salt="s10nb")
        print(ret, type(ret))
        if ret == "1":
            # 表示已经登陆过
            return render(request, "home.html")
        else:
            return redirect("/login/")
    
    @check_login
    def index(request):
    
        return render(request, "index.html")
    
    
    # 注销函数
    def logout(request):
        # 如何删除Cookie
        rep = redirect("/login/")
        rep.delete_cookie("is_login")
        return rep
    View Code


    6.Django中删除Cookie:(注销)
      rep.delete_cookie(key)

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    1.Session是什么
      Session保存在服务端的键值对 (值为自定义格式的字典)

      Session依赖于Cookie
       举个例子:
      dsadasdsadsafsjkndf: {"is_login": 1, "name": "xiaohei", "age":18}
      dsaasdaknfgreryywdf: {"is_login": 1, "name": "xiaobai", "age":20}
      wqrqrteknfgzddasqfg: {"is_login": 0, "name": "xiaohui", "age":48}

      给浏览器写入Cookie:
        sessionid:wqrqrteknfgzddasqfg

        1. 从用户发来的请求的Cookie中 根据 sessionid 取值, 取到 wqrqrteknfgzddasqfg
        2. 根据特殊字符串找到对应的 Session 数据 --> {"is_login": 0, "name": "xiaohui", "age":48}
        3. request.session.get("is_login") --> 从Session取值

    Session流程解析:


    总结cookie h和 session的区别:

    a.cookie是保存在浏览器端的键值对,而session是保存在服务端的键值对,但是依赖cookie(也可以不依赖,可以放在url,或请求头但是cookie比较方便)

    b.以登录为例,cookie为通过登录成功后,设置明文的键值对,并将键值对发送给客户端存储,明文信息可能存在安全泄漏,不安全

      session则是生成随机字符串,发送给用户,并写道浏览器的cookie中,同时服务器自己也会保存一份

    c.在验证登录时,cookie;根据浏览器发送请求是附带的cookie的键值进行判断。如果存在,则验证通过;

     session 在请求用户的cookie中获取随机字符串,根据随机字符串在session中获取其对应的值进行验证


    2.Django中设置Session:
      request.session["is_login"] = 1
      request.session.set_expiry(7) # 设置超时时间 (Cookie和Session数据的)


    3.在settings.py中设置,每次请求都刷新Session超时时间
      SESSION_SAVE_EVERY_REQUEST = True

    4.Django中删除Session:
      request.session.flush() 清除Cookie和Session数据

      request.session.clear_expired() 将所有Session失效日期小于当前日期的数据删除

    总结: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失效策略。

     Session版本的登录

    from django.shortcuts import render, redirect
    from django import views
    
    # Create your views here.
    from functools import wraps
    # Django提供的工具,把函数装饰器转变成方法装饰器
    from django.utils.decorators import method_decorator
    from django.views.decorators.csrf import csrf_exempt, csrf_protect
    
    
    def check_login(func):
        @wraps(func)  # 装饰器修复技术
        def inner(request, *args, **kwargs):
            ret = request.session.get("is_login")
            # 1. 获取cookie中的随机字符串
            # 2. 根据随机字符串去数据库取 session_data --> 解密 --> 反序列化成字典
            # 3. 在字典里面 根据 is_login 取具体的数据
            if ret == "1":
                # 已经登陆过的 继续执行
                return func(request, *args, **kwargs)
            # 没有登录过的 跳转到登录页面
            else:
                # 获取当前访问的URL
                next_url = request.path_info
                print(next_url)
                return redirect("/app02/login/?next={}".format(next_url))
        return inner
    
    
    @csrf_exempt
    def login(request):
        if request.method == "POST":
            user = request.POST.get("user")
            pwd = request.POST.get("pwd")
            # 从URL里面取到 next 参数
            next_url = request.GET.get("next")
    
            if user == "alex" and pwd == "dsb":
                # 登陆成功
                # 告诉浏览器保存一个键值对
    
                if next_url:
                    rep = redirect(next_url)  # 得到一个响应对象
                else:
                    rep = redirect("/app02/home/")  # 得到一个响应对象
                # 设置session
                request.session["is_login"] = "1"
                request.session["name"] = user
                request.session.set_expiry(7)  # 7秒钟之后失效
                return rep
    
        return render(request, "app02/login.html")
    
    
    @check_login
    def home(request):
        user = request.session.get("name")
        return render(request, "app02/home.html", {"user": user})
    
    
    @check_login
    def index(request):
    
        return render(request, "app02/index.html")
    
    
    # 注销函数
    def logout(request):
        # 只删除session数据
        # request.session.delete()
        # 如何删除session数据和cookie
        request.session.flush()
        return redirect("/app02/login/")
    
    
    # @method_decorator(check_login, name="get")
    class UserInfo(views.View):
    
        @method_decorator(check_login)
        def get(self, request):
            return render(request, "app02/userinfo.html")
    View Code
  • 相关阅读:
    制作centos镜像,启动镜像可以访问本地百度页面
    docker配置镜像加速后报错 系统 CentOS7
    代理方式获取天气预报信息
    周边分析-距离计算
    mysql随笔
    mysql笔记
    树形结构表的存储【转自:http://www.cnblogs.com/huangfox/archive/2012/04/11/2442408.html】
    Mysql中 in 和 exists 区别
    CPU飙高,系统性能问题如何排查?
    位运算的常见操作
  • 原文地址:https://www.cnblogs.com/zhanghongqi/p/11215546.html
Copyright © 2020-2023  润新知