zoukankan      html  css  js  c++  java
  • Django学习笔记一十五——cookies和session

    众所周知,HTTP是一个无状态协议,为了提高效率,比较原始的方法就是引入cookies的概念(虽然现在去cookies化是大趋势,但一时半会还是要使用cookies的。)

    从原理上来说,cookies就是保存在浏览器上的键值对,服务器控制这响应 ,在响应中可以让浏览器在本地保存这个键值对,下一次请求在发送的时候就会自动携带这个键值对(cookies值)。要注意的是cookies是服务端设置的,我们可以设置浏览器让服务端禁用cookies。但是有很多Web在登录的时候还是基于cookies的

    cookies的作用

    1.保持登录状态(几天内免登陆)

    2.记录用户的浏览器习惯(搜索记录)

    3.简单的防止刷票 

    没有cookies的使用

    在前面的登录案例中,我们都是不保持状态的,每次打开login页面都要登录,正常的视图函数是这样的

    def login(request):
        if request.method == 'POST':
            user = request.POST.get('user')
            pwd = request.POST.get('pwd')
            if user == 'hehe' and pwd =='123':
                return redirect('/home/')
        return render(request,'login.html')

    我们每次在打开登录页面,在POST用户名和密码以后,都会进行一次登录操作。如果登录成功,就直接跳转到下一步操作,但是每次进入login页面都要进行一次登录。

    把cookies引入登录程序

    引入cookies 

    引入cookies的方法也比较简单,我们先看一看是怎么在程序中加载cookies的

    def login(request):
        if request.method == 'POST':
            user = request.POST.get('user')
            pwd = request.POST.get('pwd')
            if user == 'hehe' and pwd =='123':
                rep = redirect('/home/')    #得到一个响应对象
                rep.set_cookie('123','abc') #设置cookies
                return rep
        return render(request,'login.html')

    在上面的这段代码中,我们再生成一个相应对象以后对这个对象添加一个cookies以后,直接返回对象。在登录进入主页以后,重新刷新一遍,我们检查一下页面(Network)

     检查一下cookies,是不是多了一个键值对,key和value就是我们在代码中添加的。

    cookies的获取

    再次进入home页面以后,我们可以在获取COOKIES

    def home(request):
        ret = request.COOKIES['123']
        print(ret)
        return render(request,'home.html')

    然后可以对COOKIES进行比较如果,来判定是否已经登录

    COOKIES的保存时间

    默认情况下COOKIES的保存时间是随着浏览器的,浏览器一旦关闭COOKIES就失效。

    登录时的COOKIES

     我们可以把COOKIES的键值对设置成{'is_loged':0},然后在登录主页的时候获取这个COOKIES,然后进行比对,如果比对成功,直接进入主页,否则跳转至登录页面。

    def login(request):
        if request.method == 'POST':
            user = request.POST.get('user')
            pwd = request.POST.get('pwd')
            if user == 'hehe' and pwd =='123':
                rep = redirect('/home/')    #得到一个响应对象
                rep.set_cookie('is_loged','1') #设置cookies
                return rep
        return render(request,'login.html')
    
    
    def home(request):
        ret = request.COOKIES.get('is_loged',0) #获取COOKIES
        if ret == '1':
            return render(request,'home.html')
        else:
            return redirect('/login/')

    这样就实现了免登陆的效果。

     装饰器版的登录校验

    在平时我们访问网站的时候,比方上淘宝,在每个页面都是有登录状态的,我们就要在每个页面添加一个登录校验的过程,可是有些页面是已经使用了,那么就到了装饰器的使用时间了。先看一下代码

    #定义装饰器函数
    def login_check(func):
        @wraps(func)      #装饰器修复技术
        def inner(request,*args,**kwargs):
            ret = request.COOKIES.get('is_logged',0)
            if ret == '1':
                return func(request,*args,**kwargs)
            else:
                return redirect('/login/')
        return inner
    
    
    
    def login(request):
        if request.method == 'POST':
            user = request.POST.get('user')
            pwd = request.POST.get('pwd')
            if user == 'hehe' and pwd =='123':
                rep = redirect('/home/')    #得到一个响应对象
                rep.set_cookie('is_logged','1',max_age=10) #设置cookies
                return rep
        return render(request,'login.html')
    
    
    #用装饰器来修饰页面判定登录情况
    @login_check
    def home(request):
        return  render(request,'home.html')

    上面这段程序的流程就是在对home页面发出请求的时候,通过装饰器函数login_check检查cookies里的登录状态,如果已经登录,就进入home页面,否则就进入登录的页面。等待登录。但是这种用法有个问题所以不大常用:如果有好多个页面在请求的时候倒要进行判定,在每个视图函数前面都要加个这个装饰器。那就要用到后面会讲到的中间件。

    Session的使用

    从Cookie到Session

    虽然我们用Cookie在一定成都上解决了Http请求保持状态的需求,但是Cookie本身最大只能支持4096字节,并且由于Cookie是保存在浏览器里的,即便是用了加密盐,也很有可能被拦截或窃取,安全性很难保证。

    于是,一种新的方案就出来了,我们给浏览器的Cookie分配一个唯一的id,用户在访问的时候,通过Cookie里的id从服务端取到保存了某段时间内的用户私密资料,比方登录状态,账号密码等。这样,几乎所有的数据都是存在服务器端,就没有数据大小的限制,并且由于数据是存放在服务器里,安全也相对来说高一些。

    Session的优缺点

    优点:

    比Cookie存档数据多

    安全性好

    缺点

    Session的数据量大,会占用一些服务器的资源,并且在请求量大时加大了服务器的负载。

    Django内Session的相关方法

    在Django内,Session的工作也就是下面几条:

    • 存Session
      • 在服务端生成一个随机的字符串

      • 生成一个上面的随机字符串的大字典来保存用户的数据
      • 生成的随机字符串作为Cookie返回给浏览器

    • 取Session
      • 从请求携带的Cookie中找到那个随机的字符串
      • 拿到字符串去Session中找对应的大字典
      • 从大字典内根据Key找值

    并且Session是在settings里绑定的数据库中的,我们可以查一下

     上面的数据就是新添加 了一条Session内容以后数据库的数据。session_key就是Cookie里存储的那个随机的字符串

     而那个前面说的大字典就是以密文的方式保存在session_data字段里的数据。但是有一点要注意,这个数据是只要有一个浏览器的请求一个session,过来,就会生成一个。你开两个页面就会有两条内容

    获取、设置、删除Session内的数据

    request.session['key'] = value                #设置session中的键值对
    request.session['key']                        #获取session中的key对应的value
    request.session.flush()                       #删除当前会话并删除会话中的Cookie

    我们从下面一个登录、浏览主页和注销的页面来演示一下session是怎么使用的。

    def login(request):
        if request.method == 'POST':
            name = request.POST.get('user')
            pwd = request.POST.get('pwd')
    
            if name == 'aaa' and pwd =='bbb':
                rep = HttpResponse('登录成功')
                request.session['is_log'] = 1   #session中添加登录状态
                request.session['user'] = name  #session中添加内容
                request.session.set_expiry(10)  # 10秒钟之后失效
                return rep
            
            else:
                return redirect('/session_test/login')
        else:
            return render(request,'login.html')
    
    
    #浏览主页并检查登录状态
    def home(request):
        print(request.session.get('is_log'))
        if request.session.get('is_log') == 1:
            return  render(request,'home.html')
        else:
            return redirect('/session_test/login')
    
    #注销然后进入登录页面
    def clear_session(request):
        request.session.flush()
        return redirect('/session_test/login')
    Session入门使用

    所有的键值对

    request.sesssion.keys()    -->    <class 'dict_keys'>     #获取session内所有key
    request.session.values() -->  <class 'dict_values'>    #获取session内所有values
    request.session.values()  --><class 'dict_items'>   #获取session键值对
    #打印的结果dict_items([('is_log', 1), ('user', 'aaa'), ('_session_expiry', 100)]) <class 'dict_items'>

    session中生成的随机字符串

    request.session.session_key

    注意这不是个方法,不用带括号。

    session的清除

    删除当前用户的所有Session数据

    request.session.delete('session_key')#删除session_key对应的session内数据,但是只会删除session,但是Cookie里的随机字符串还在
    request.session.flush() #删除session和Cookie
    request.session.clear_expired()    #删除所有session失效日期小于当前日期的数据
    
    request.session.set_expiry(value)   #session的失效策略
    #默认的过期时间是两周,如果自己设置了过期时间,这样自己设定的优先级就会高于默认的
    #如果value是个整数,session会在些秒数后失效。
    #如果value是个datatime或timedelta,session就会在这个时间后失效。
    #如果value是0,用户关闭浏览器session就会失效。
    #如果value是None,session会依赖全局session失效策略。

    那个clear_expired()常常用来定时清除过期的Session来释放空间。

     session的失效策略是通过Cookie的失效来实现的,如果超过指定时间,Cookie就不在存储那个随机字符串,但是Session大字典的内容是还在数据库中,必须手动调用上面那条指令来释放。

    Session在settings内的设置

    session还可以通过下面的内容进行设置,直接加载settings.py文件后面就行了

    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,默认修改之后才保存(默认)
    Session的设置

     装饰器版的Session使用

    最后看一下装饰器版的Session是怎么使用的,和Cookie一样,用一个页面的请求来判定登录状态

    from functools import wraps
    #检查登录状态的装饰器
    def check_login(func):
        @wraps(func)
        def inner(request,*args,**kwargs):
            ret = request.session.get('is_log')
            if ret == 1:
                return func(request,*args,**kwargs)
    
            else:
                return redirect('/session_test/login/')
    
        return inner
    def login(request):
        return HttpResponse(12345656)
    
    def login(request):
        if request.method == 'POST':
            name = request.POST.get('user')
            pwd = request.POST.get('pwd')
    
            if name == 'aaa' and pwd =='bbb':
                rep = HttpResponse('登录成功')
                request.session['is_log'] = 1   #session中添加登录状态
                request.session['user'] = name  #session中添加内容
                request.session.set_expiry(100)  # 10秒钟之后失效
                return rep
            
            else:
                return redirect('/session_test/login')
        else:
            return render(request,'login.html')
    
    
    
    #用装饰器检查登录状态
    @check_login
    def home(request):
        return render(request,'home.html')
    View Code
  • 相关阅读:
    归并排序
    数据组合求值
    轨道周期
    类及对象构建
    日期改写
    排列组合去重
    库存更新
    Java性能测试从入门到放弃-详解篇
    Java性能测试从入门到放弃-概述篇
    cocos2d-x安装教程
  • 原文地址:https://www.cnblogs.com/yinsedeyinse/p/12799403.html
Copyright © 2011-2022 走看看