• day55:django:cookie&session


    目录

    1.Cookie

      1.Cookie前戏

      2.Cookie的引入

      3.django中操作cookie

    2.Session

      1.cookie的局限性

      2.session技术

      3.django操作session

      4.Session详细流程解析

      5.session实例分析

      6.对于cookie和session的总结

    3.django外部脚本调用django环境

    4.基于session和中间件完成登录认证

    Cookie

    1.Cookie前戏

    HTTP协议的两个特点

    1.无连接

    将协议设计为请求时建连接、请求完释放连接,以尽快将资源释放出来服务其他客户端。

    2.无状态

    什么是无状态?

    无状态的意思是每次请求都是独立的

    它的执行情况和结果与前面的请求和之后的请求都无直接关系,

    它不会受前面的请求响应情况直接影响,

    也不会直接影响后面的请求响应情况

    简单的来说:无状态是指服务器不知道客户端是什么状态

    对于无状态的解释

    要明白,这句话的含义是指在说明,http协议作为技术背景的web应用程序请求——应答模式是无状态的,这个事实基本不会发生改变,也不会因为加入cookies、session机制而变成有状态的。

    要明白,这种前后因果关系:“我们要实现的是一种web应用,实现这种应用的协议我们选择了http这种本质上是无状态的通信协议

    但是事实上,我们需要我们的web应用是有状态的。所以我们加入了cookies、session等机制去实现有状态的web应用。

    2.Cookie的引入

    1.cookie的引入

    因为http无状态,所以出现了cookie,cookie是一种浏览器技术

    2.cookie能做什么?

    1.浏览器访问服务端,带着一个的cookie,

    2.然后由服务器产生内容浏览器收到相应后保存在本地

    3.当浏览器再次访问时,浏览器会自动带上Cookie,这样服务器就能通过Cookie的内容来判断这个是“谁”了。

    3.cookie规范

    •  Cookie大小上限为4KB; 
    •  一个服务器最多在客户端浏览器上保存20个Cookie; 
    •  一个浏览器最多保存300个Cookie,因为一个浏览器可以访问多个服务器。

        上面的数据只是HTTP的Cookie规范,但在浏览器大战的今天,一些浏览器为了打败对手,为了展现自己的能力起见,可能对Cookie规范“扩展”了一些,例如每个Cookie的大小为8KB,最多可保存500个Cookie等!但也不会出现把你硬盘占满的可能! 
    注意,不同浏览器之间是不共享Cookie的。也就是说在你使用IE访问服务器时,服务器会把Cookie发给IE,然后由IE保存起来,当你在使用FireFox访问服务器时,不可能把IE保存的Cookie发送给服务器。

    4.cookie和HTTP头

     Cookie是通过HTTP请求和响应头在客户端和服务器端传递的: 

    • Cookie:请求头,客户端发送给服务器端; 
    • 格式:Cookie: a=A; b=B; c=C。即多个Cookie用分号离开; 
    • Set-Cookie:响应头,服务器端发送给客户端; 
    • 格式:一个Cookie对象一个Set-Cookie: Set-Cookie: a=A Set-Cookie: b=B Set-Cookie: c=C  

    5.cookie的覆盖

    如果服务器端发送重复的Cookie那么会覆盖原有的Cookie,例如客户端的第一个请求服务器端发送的Cookie是:Set-Cookie: a=A;第二请求服务器端发送的是:Set-Cookie: a=AA,那么客户端只留下一个Cookie,即:a=AA。 

    3.django中操作cookie

    cookie的获取/设置/修改/删除

    1.获取cookie

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

    2.设置cookie

    # 设置cookie
    '''cookie的获取都是基于request对象的'''
    '''cookie的设置都是基于HttpResponse对象的'''
    rep = HttpResponse(...)
    rep = render(request, ...)
    rep.set_cookie(key,value,...)
    rep.set_signed_cookie(key,value,salt='加密盐', max_age=None, ...)

    3.修改cookie

    # 修改cookie
    ret.set_cookie('username', 'xxx')  #相同的键设置不同的值就是修改

    4.删除cookie

    # 删除cookie
    ret.delete_cookie('username')

    cookie参数的意义

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

    Session

    1.cookie的局限性

    1.cookie是明文存储

    2.cookie的大小限制

      Cookie大小上限为4KB;

      一个服务器最多在客户端浏览器上保存20个Cookie;

      一个浏览器最多保存300个Cookie,因为一个浏览器可以访问多个服务器。

    2.session技术

    session比cookie的强大之处

    Cookie虽然在一定程度上解决了“保持状态”的需求,但是由于Cookie本身最大支持4096字节,以及Cookie本身保存在客户端,可能被拦截或窃取,

    因此就需要有一种新的东西,它能支持更多的字节,并且他保存在服务器,有较高的安全性。这就是Session

    cookie的桥接作用

    问题来了,基于HTTP协议的无状态特征,服务器根本就不知道访问者是“谁”。那么上述的Cookie就起到桥接的作用。

    我们可以给每个客户端的Cookie分配一个唯一的id,这样用户在访问时,通过Cookie,服务器就知道来的人是“谁”。

    然后我们再根据不同的Cookie的id,在服务器上保存一段时间的私密资料,如“账号密码”等等。

    cookie和session各自实现的功能总结

    总结而言:Cookie弥补了HTTP无状态的不足,让服务器知道来的人是“谁”;

           但是Cookie以文本的形式保存在本地,自身安全性较差;

         所以我们就通过Cookie识别不同的用户,对应的在Session里保存私密的信息以及超过4096字节的文本。

    3.django操作session

    # 设置session
    request.session['k1'] = 123
    request.session.setdefault('k1',123)
    
    # 获取session
    request.session['k1'] 
    request.session.get('k1',None)
    
    # 删除session
    del request.session['k1']
    
    # 清空session
    request.session.flush()

    4.Session详细流程解析

    5.session实例分析

    这是一段登录的视图函数,在函数中添加两个session,在添加session时,做了三件事

    def login(request):
        if request.method == 'GET':
            return render(request, 'login.html')
        else:
            uname = request.POST.get('username')
            if uname == 'root' or uname=='abc':
                request.session['is_login'] = True
                request.session['username'] = uname
                # request.session
                # 1 生成一个随机字符串
                # 2 将随机字符串放到cookie中,名称为sessionid
                # 3 将设置的session数据,序列化+加密,保存到了django-session表中
                return redirect('/home/')
            else:
                return redirect('/login/')

    这是一段注销的视图函数,这个时候我们要删除session,在删除session时,做了两件事

    def logout(requset):
        requset.session.flush()
        # 1 删除cookie中的数据
        # 2 删除数据库中django-session表中的记录
        return redirect('/login/')

    这是一个基于session的登录认证中间件,这个时候我们要查session中某个键的值,在查session的时候,做了三件事

    # 基于session的登录认证中间件
    class LoginAuth(MiddlewareMixin):
        white_list = ['/login/', ]  # 白名单
        def process_request(self,request): 
            path = request.path # 获取当前请求路径
            if path not in self.white_list: # 如果路径不在白名单内
                is_login = request.session.get('is_login') # 获取session中is_login的值
                # request.session['is_login']
                # 1 取出请求中cookie键为sessionid的值
                # 2 通过这个值到django-session表中获取数据
                # 3 将数据解密并且反序列化得到原来的数据
                if is_login != True:
                    return redirect('/login/')

    6.对于cookie和session的总结

    # 0.session你需要注意的点
    '''
    注意:1.session数据是保存在服务端的(存在?),给客户端返回的是一个随机字符串
    然后给这个随机字符串配一个固定的键 这个键叫做sessionid,也就是说sessionid存储的就是随机字符串
    2.在默认情况下操作session的时候需要django的默认一张django_session表
    django_session表中存放着三个字段:session_key session_data expire_data
    3.django默认session的过期时间是14天,但是你也可以人为的修改它
    4.django_session表中的数据条数是取决于浏览器的
        同一个计算机上同一个浏览器只会有一条数据。
        如果是不同的浏览器,就会有多条数据
        但是当session过期的时候可能会出现多条数据对应一个浏览器,但是这种现象不会持续很久,django内部会自动识别过期的数据清除,你也可以通过代码去清除
    5.session是保存在服务端的,但是session的保存位置可以有多种选择
        1.可以存在自己的mysql数据库中
        2.可以存在文件里面
        3.可以存在缓存中:redis,memcache
    '''
    
    # 1.django中的session操作 【设置 获取 修改 删除】
    '''
    1.设置session
    request.session['key'] = value
    
    2.获取session
    request.session.get('key')
    
    3.设置session过期时间
    request.session.set_expiry()
        括号内可以放四种类型参数
            1.整数:多少秒
            2.日期对象:Datetime 到了指定日期就失效
            3.0:一旦当前浏览器窗口关闭 立刻失效
            4.什么都不写:失效时间就取决于django内部全局session默认的失效时间(14天)
    
    4.清除session
    request.session.delete() : 只删服务端的 客户端的不删
    request.session.flush() :浏览器和服务端都清空[常用]
    
    5.像设置字符串和获取字符串,是可以做一个加盐(加密)处理的,不是很重要就不细说了....
    
    5.session还有很多属性,在这就不再一一介绍了
    '''
    
    # 2.知道这些了,我们先来搞一个session操作
    '''
    1.配置一个url,叫做set/session,并且定义视图函数set_session
    2.def set_session(request):
        request.session['hobby']='girl'
        return HttpResponse('ok')
    3.运行django项目 然后去django_session表中查看 会发现django_session表中多了一条数据
    4.现在设置session没有问题了,那么如何获取session呢?
    5.再配置一个url,叫做get/session,并且定义视图函数get_session
    def get_session(request):
        print(request.session.get('hobby'))
        return HttpResponse('ok')
    6.运行django项目 进入get/session路径 可以打印出girl,girl就是session键对应的值
    7.现在设置session和获取session都已经成功了,接下来分析设置session和获取session内部究竟做了什么事
    request.session['hobby']='girl'
        1.django内部会自动帮你生成一个随机字符串
        2.django内部自动将随机字符串和对应的数据存储在django-session表中
            1.先在内存中产生操作数据的缓存
            2.在响应经过django中间件的时候才真正的操作数据库
        3.将产生的随机字符串返回给客户端浏览器保存
    request.session.get('hobby')
        1.自动从浏览器请求中获取sessionid对应的随机字符串
        2.拿着该随机字符串去django-session表中查找对应的数据
        3.进行比对
            如果比对上了,则将对应的数据取出并以字典的形式封装到request.session中
            如果比对不上,则request.session.get()返回的值是None
    --------------------------------------------------------------------------------------
    8.session除了设置和获取,也有一些额外的操作
        1.session设置值可以设置多个的
            request.session['hobby1']='girl1'
            request.session['hobby2']='girl2'
            request.session['hobby3']='girl3'
            request.session['hobby4']='girl4'
            那问题就来了,如果设置了四个session,在django_session表中是有一条数据还是多条数据呢?
                在django_session表中,只有一条数据,但是你设置了四个session,你可以通过四个request.session.get(key)分别获取他们的value,四个是都可以打印出来的
                为什么session只有一条数据呢?如果每存一次开辟一个新的数据,数据库表数据会难以承担,为了节省服务端资源
    9.知道了如何删除session,那我们现在定义一个视图函数del_session
    def del_session(request):
        request.session.delete()
        return HttpResponse('ok')
    '''

    django外部脚本调用django环境

    import os
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "django_cookie.settings")
    import django
    django.setup()
    
    from app01 import  models
    models.Book.objects.create(
        title='xxx',
        price=200,
    )

    基于session和中间件完成登录认证

    简单来说,就是你登录了,才可以访问那些首页 添加页面那些url

    而当你没有登录的时候,是不能够访问这些url的

    登录的视图函数

    当你登录成功的时候,将session中的is_login设置为True

    def login(request):
        if request.method == 'GET':
            return render(request,'login.html')
        else:
            username = request.POST.get('username')
            if username == 'root': # 当用户名输入正确的时候,让session的is_login的值为True
                request.session['is_login'] = True
                return redirect('/book/list')
            else:
                return HttpResponse('username error')

    基于session和中间件的登录认证类

    class Auth(MiddlewareMixin):
        """
        基于session的登录认证中间件
        """
        white_lst = ['/login/',] # 白名单
        def process_request(self,request):
            path = request.path # 获取当前请求路径
            if path not in self.white_lst:
                # 判断当前请求路径是否在白名单中
                '''
                1.如果在白名单中,无需经过session认证 直接可以显示界面
                2.如果不在白名单中,通过request.session.get获取到session中的is_login值
                  根据is_login的值判断用户是否登录
                    a.如果is_login的值为True,代表用户已经登录,所以通过验证
                    b.如果is_login的值为False,代表用户没有登录,不能通过验证,所以进不了其他界面,返回到login
                '''
                is_login = request.session.get('is_login')
                if is_login != True:
                    return redirect('/login/')
  • 相关阅读:
    201671030116宋菲菲 实验三作业互评与改进报告
    通读《构建之法》提出问题
    201671010460-朱艺璇-实验四附加实验
    201671010460朱艺璇 词频统计软件项目报告
    201671010460朱艺璇 实验三作业互评与改进报告
    阅读《现代软件工程—构建之法》提出的问题
    手把手带你了解消息中间件(3)——RocketMQ
    字符编码的历史由来
    linux常用命令
    linux各目录及重要目录的详细介绍
  • 原文地址:https://www.cnblogs.com/libolun/p/13713702.html
Copyright © 2020-2023  润新知