zoukankan      html  css  js  c++  java
  • 9.djang -- cookie和session

    djang -- cookie和session

    一.cookie -- 小甜点

    1.由来

    http协议,两个特点: 无状态、无连接(http//1.1版本后短连接)
    	无状态:  -- http协议不会记录客户端和服务端的任何状态信息,每次请求都是独立的,导致不能维持会话
    	状态可以理解为客户端和服务器在某次会话中产生的数据,那无状态的就以为这些数据不会被保留。会话中产生的数据又是我们需要保存的,也就是说要“保持状态”。因此Cookie就是在这样一个场景下诞生。
    	访问哪一个网址,都要验证用户的身份,但是还有保证什么呢,用户登陆过之后,还要保证登陆了的用户不需要再重复登陆,就能够访问我网站的其他的网址的页面,对不对,但是http无状态啊,怎么保证这个事情呢?此时就要找cookie了。
    

    2.什么是cookie

    	cookie是浏览器的技术,Cookie具体指的是一段小信息,它是服务器发送出来存储在浏览器上的一组组键值对,可以理解为服务端给客户端的一个小甜点,下次访问服务器时浏览器会自动携带这些键值对,以便服务器提取有用信息。
    

    3.cookie原理

    	cookie的工作原理是:浏览器第一次访问服务端,带着一个空的cookie,然后由服务器产生内容,浏览器收到相应后保存在本地;当浏览器再次访问时,浏览器会自动带上Cookie,这样服务器就能通过Cookie的内容来判断这个是“谁”了。
    

    4.基于cookie的登陆认证

    路由:urls.py

    from app01 import views
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^login/', views.login, name='login'),
        url(r'^home/', views.home,name='home'),
        url(r'^person/', views.person,name='person'),
    ]
    

    视图:views.py -- 写cookie登陆认证

    from django.shortcuts import render,redirect
    
    def login(request):
    
        if request.method == 'GET':
            return render(request,'login.html')
        else:
            uname = request.POST.get('username')
            pwd = request.POST.get('password')
            if uname == 'jia' and pwd == '123': # 用户名密码输入正确才添加cookie
                ret = redirect('home')
                # ret.set_cookie('is_login',True) #设置cookie键值对
                ret.set_cookie('is_login',True,5) #设置cookie数据5秒后清除
                ret.set_cookie('uname', uname) #可以设置多个值
    
                return ret
                # 浏览器响应头中有Set-Cookie: is_login=True;显示cookie数据
            else:
                return redirect('login')
    
    def home(request): # 我们要求:没有登陆,不能直接访问home页面
    
        print(request.COOKIES)
        # 可以拿到本次访问携带的cookie字典数据
        # {'is_login': 'True', 'uname': 'jia'}
        # 网络传输 -- bytes类型数据(编码处理) -- 所以值都是字符串了
    
        # 基于cookie的登录认证(判断用户是否处于登录状态)
        is_login = request.COOKIES.get('is_login')
        # cookie中有登录成功之后的标识信息才能正常访问home页面
        # 不然就让它去login页面登录
        if is_login == 'True':
            return render(request,'home.html')
        else:
            return redirect('login')
    

    templates目录下HTML文件:

    login.html

    <body>
    <form action="" method="post">
        用户名: <input type="text" name="username">
        密码: <input type="password" name="password">
        <input type="submit">
    </form>
    </body>
    

    home.html

    <body>
    <h1>这是首页</h1>
    <a href="{% url 'person' %}">个人中心</a>
    </body>
    

    5.cookie登录认证装饰器

    视图:views.py ,其他同上

    from django.shortcuts import render,redirect,HttpResponse
    
    # 基于cookie的登录认证装饰器
    def outer(func):
        def inner(request,*args,**kwargs):
            is_login = request.COOKIES.get('is_login')
            if is_login == 'True':
                res = func(request,*args,**kwargs)
                return res
            else:
                return redirect('login')
        return inner
    
    @outer  # 访问其他页面时登陆认证加装饰器
    def person(request):
        return render(request,'person.html')
    
    @outer
    def home(request):
        return render(request, 'home.html')
    
    def login(request):
    
        if request.method == 'GET':
            return render(request,'login.html')
        else:
            uname = request.POST.get('username')
            pwd = request.POST.get('password')
            if uname == 'jia' and pwd == '123': # 用户名密码输入正确才添加cookie
                ret = redirect('home')
                # ret.set_cookie('is_login',True) #设置cookie键值对
                ret.set_cookie('is_login',True,5) #设置cookie数据5秒后清除
                ret.set_cookie('uname', uname) #可以设置多个值
    
                return ret
                # 浏览器响应头中有Set-Cookie: is_login=True;显示cookie数据
            else:
                return redirect('login')
    

    6.django中操作cookie

    设置cookie
    rep = HttpResponse(...)
    rep = render(request, ...)
    
    rep.set_cookie(key,value,...) #包含添加和修改,键和值
    # 设置签名cookie --  
    # rep.set_signed_cookie(key,value,salt='加密盐', max_age=None, ...)
    
    获取cookie
    request.COOKIES.get('is_login')
    request.COOKIES['key']
    # 获取签名cookie
    # request.get_signed_cookie(key, default=RAISE_ERROR, salt='', max_age=None)
    
    删除cookie
    def logout(request):
        rep = redirect("/login/")
        rep.delete_cookie("user")  # 删除用户浏览器上之前设置的usercookie值
        return rep
    

    7.Set_cookie方法

    class HttpResponseBase:
    
            def set_cookie(self, 
       key,            键
       value='',       值
       max_age=None,   有效时间,max_age=20意思是这个cookie20秒后就消失了,默认时长是2周,这个是以秒为单位的,cookie需要延续的时间(以秒为单位),如果参数是 None`` ,这个cookie会延续到浏览器关闭为止。
    
       expires=None,   有效时间,值是一个datetime类型的时间日期对象,到这个日期就失效的意思,用的不多,expires默认None ,cookie失效的实际日期/时间。 
                                    
    
       path='/',       指定Cookie生效的路径,就是访问哪个路径可以得到cookie,'/'是所有路径都能获得cookie,浏览器只会把cookie回传给带有该路径的页面,这样可以避免将cookie传给站点中的其他的应用。 / 表示根路径,特殊的:根路径的cookie可以被任何url的页面访问
                         
       domain=None,    Cookie生效的域名,你可用这个参数来构造一个跨站cookie。
                       如, domain=".example.com",所构造的cookie对下面这些站点都是可读的:
                          www.example.com 、 www2.example.com
                       如果该参数设置为 None ,cookie只能由设置它的站点读取。
    
       secure=False,   如果设置为 True ,浏览器将通过HTTPS来回传cookie。HTTP不生效
       httponly=False  如果为True,只能http协议传输,无法被JavaScript获取(不是绝对,底层抓包可以获取到也可以被覆盖)
                   	): pass
    

    8.cookie设置中文时的编码问题:(了解)

    • 所以尽量不要出现中文

    cookie在设置时不允许出现中文。非要设置中文的怎么办,看下面的解决方案:

    # 方式1
    def login(request):
    
        ret = HttpResponse('ok')
        
        ret.set_cookie('k1','你好'.encode('utf-8').decode('iso-8859-1'))
        
        #取值:request.COOKIES['k1'].encode('utf-8').decode('iso-8859-1').encode('iso-8859-1').decode('utf-8')
    
        return ret
    
    方式2 json
    
    def login(request):
    
        ret = HttpResponse('ok')
        
        import json
    
        ret.set_cookie('k1',json.dumps('你好'))
        #取值 json.loads(request.COOKIES['k1'])
        return ret
    

    9.Cookie规范

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

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

    10.cookie的缺点:

    1 存储数据的大小有上限
    2 明文存储数据 (不安全,敏感数据尽量不要通过cookie存储)
    

    为了解决cookie的弊端,session技术出现了

    二.session

    1.简介:

     Session是服务器端技术,Django的session技术是基于cookie实现的,利用这个技术,服务器在运行时可以 为每一个用户的浏览器创建一个其独享的session对象,
    cookie缺点:
        1 存储数据的大小有上限
        2 明文存储数据 (数据储存在客户端浏览器,不安全,敏感数据尽量不要通过cookie存储)
    session优点:
        1.数据存在服务端,比较安全,存储大小无上限
        2.传输效率也高,cookie中只有一对随机字符串
        
    问题来了,基于HTTP协议的无状态特征,服务器根本就不知道访问者是“谁”。那么上述的Cookie就起到桥接的作用。
    
      我们可以给每个客户端的Cookie分配一个唯一的id,这样用户在访问时,通过Cookie,服务器就知道来的人是“谁”。然后我们再根据不同的Cookie的id,在服务器上保存一段时间的私密资料,如“账号密码”等等。
    
      总结而言:Cookie弥补了HTTP无状态的不足,让服务器知道来的人是“谁”;但是Cookie以文本的形式保存在本地,自身安全性较差;所以我们就通过Cookie识别不同的用户,对应的在Session里保存私密的信息以及超过4096字节的文本。
    
      另外,上述所说的Cookie和Session其实是共通性的东西,不限于语言和框架。
    

    2.django操作session

    基于session的登录认证

    视图:views.py -- 其他页面与cookie一样

    from django.shortcuts import render,redirect,HttpResponse
    
    # 基于session的登录认证装饰器
    def outer(func):
        def inner(request,*args,**kwargs):
            is_login = request.session.get('is_login')
            if is_login:
                res = func(request,*args,**kwargs)
                return res
            else:
                return redirect('login')
        return inner
    
    def login(request):
    
        if request.method == 'GET':
            return render(request,'login.html')
        else:
            uname = request.POST.get('username')
            pwd = request.POST.get('password')
            if uname == 'jia' and pwd == '123':
                ret = redirect('home')
                # 以键值方式设置session
                request.session['is_login'] = True
                request.session['uname'] = uname
                '''
                    1 生成随机字符串asdf,放到cookie中(sessionid:asdf)
                    2 在数据库表(django-session,先进行数据库同步指令)中,
                        数据表中有三个字段: 
                            data = 字段序列化然后加密is_login和uname数据
                            session_key    --> asdf 随机字符串
                            session_data   --> data 加密数据
                            session_expire --> 默认两周 有效时间
                '''
                return ret
            else:
                return redirect('login')
    
    @outer  #加session登陆认证装饰器
    def person(request):
        return render(request, 'person.html')
    
    def home(request):
    
        # 获取session
        is_login = request.session.get('is_login')
        '''
            1 取出本次cookie中的sessionid对应的值asdf随机字符串
            2 拿着asdf随机字符串去django-session表中获取保存的那条记录
            3 将该记录中的session_data进行解密并反序列化,然后取出is_login键对应的值
        '''
        print(is_login, type(is_login))  # True <class 'bool'>
        if is_login:
            return render(request, 'home.html')
        else:
            return redirect('login')
    
    session的基本操作
    # 1.取值
    request.session['k1'] 
    request.session.get('k1',None) #request.session这句是帮你从cookie里面将sessionid的值取出来,将django-session表里面的对应sessionid的值的那条记录中的session-data字段的数据给你拿出来(并解密),get方法就取出k1这个键对应的值
    
    # 2.设置值
    request.session['k1'] = 123
    request.session.setdefault('k1',123) # 存在则不设置
    
    # 3.删除值,删除某个键值对
    del request.session['k1']  #django-session表里面同步删除
    
    # 4.所有 键、值、键值对
    request.session.keys()
    request.session.values()
    request.session.items()
    
    # 5.会话session的key
    session_key = request.session.session_key  获取sessionid的值
    
    # 6.将所有Session失效日期小于当前日期的数据删除,将过期的删除
    request.session.clear_expired()
    
    # 7.检查会话session的key在数据库中是否存在
    request.session.exists("session_key") #session_key就是那个sessionid的值
    
    # 8.删除当前会话的所有Session数据
    request.session.delete()
    
    # 9.删除当前的会话数据并删除会话的Cookie。
    request.session.flush()   # 删除cookie中的sessionid值,并且同步删除数据库的记录
    
    # 10.设置会话Session和Cookie的有效期设置
    request.session.set_expiry(value)
        * 如果value是个整数,session会在些秒数后失效。
        * 如果value是个datatime或timedelta,session就会在这个时间后失效。
        * 如果value是0,用户关闭浏览器session就会失效。
        * 如果value是None,session会依赖全局session失效策略。
    

    一个服务端对应一个浏览器(一个页面只能登陆一个用户),只有一个sessionid

    Django中的session配置
    1. 数据库Session
    SESSION_ENGINE = 'django.contrib.sessions.backends.db'   # 引擎(默认)
    
    2. 缓存Session
    SESSION_ENGINE = 'django.contrib.sessions.backends.cache'  # 引擎
    SESSION_CACHE_ALIAS = 'default'                            # 使用的缓存别名(默认内存缓存,也可以是memcache),此处别名依赖缓存的设置
    
    3. 文件Session
    SESSION_ENGINE = 'django.contrib.sessions.backends.file'    # 引擎
    SESSION_FILE_PATH = None                                    # 缓存文件路径,如果为None,则使用tempfile模块获取一个临时地址tempfile.gettempdir() 
    
    4. 缓存+数据库
    SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db'        # 引擎
    
    5. 加密Cookie Session
    SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies'   # 引擎
    
    其他公用设置项:
    SESSION_COOKIE_NAME = "sessionid"                       # Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串(默认)
    SESSION_COOKIE_PATH = "/"                               # Session的cookie保存的路径(默认)
    SESSION_COOKIE_DOMAIN = None                             # Session的cookie保存的域名(默认)
    SESSION_COOKIE_SECURE = False                            # 是否Https传输cookie(默认)
    SESSION_COOKIE_HTTPONLY = True                           # 是否Session的cookie只支持http传输(默认)
    SESSION_COOKIE_AGE = 1209600                             # Session的cookie失效日期(2周)(默认)
    SESSION_EXPIRE_AT_BROWSER_CLOSE = False                  # 是否关闭浏览器使得Session过期(默认)
    SESSION_SAVE_EVERY_REQUEST = False                       # 是否每次请求都保存Session,默认修改之后才保存(默认)
    
  • 相关阅读:
    ok6410驱动usb摄像头
    自己动手写CPU之第五阶段(1)——流水线数据相关问题
    ListView嵌套ListView时发生:View too large to fit into drawing cache的问题
    算法导论 第8章 线性时间排序(计数排序、基数排序、桶排序)
    Android_通过ContentObserver监听短信数据变化
    【MyEcplise】导入项目报错:Errors running builder 'JavaScript Validator' on project '项目名'. java.lang.ClassCastException
    【js】js中const,var,let区别
    【Node.js】2.开发Node.js选择哪个IDE 开发工具呢
    【Node.js】1.安装步骤
    【POI】对于POI无法处理超大xls等文件,官方解决方法【已解决】【多线程提升速率待定】
  • 原文地址:https://www.cnblogs.com/jia-shu/p/14589832.html
Copyright © 2011-2022 走看看