zoukankan      html  css  js  c++  java
  • django-cookie和session

    一、cookie
    写cookie和session之前,先说说http协议
    它是:请求-->响应的模式,必须浏览器(客户端)向服务器发出请求之后,服务器才会响应回你了
         无状态:就是因为这点才会有cookie这些的由来,无状态就是你的上一次请求,本次请求,下一次请求
                都是毫无关联的,就好比你拨打人工服务(发出一个请求),下一次你再拨打人工服务(再一次请求),
                她会知道你是谁吗?
         无连接:意思就是你发出请求,服务器响应你了,同时会立马关闭此次链接。
    
    
    现在我们访问某些网站,比如TB网,B站,你在上面登陆了账号,下次再访问的话,还是你自己信息在那里,不是说http协议
    是无状态的吗?那我下一次访问服务器就会知道是我在访问网站呢?这就是cookie的作用了。
    
    你在访问一个网站,并且登陆了账号,它的服务器会为你这次请求生成一个cookie并且响应回你,你的浏览器就会保存起来,
    下一次再访问该网站的时候,会把这个cookie带上(放在请求头中),这样服务端后台拿到你的cookie,就知道你的身份,并
    把你的身份信息也返回到你的网页。这个cookie就相当于你的身份标志了。
    
    一个浏览器可以保存多个cookie?那访问网页的时候,会把所有的cookie都带上?肯定不会这样的,你访问特定的网站,浏览
    器内部会帮你处理,带上相应的cookie,不会带上其他网页的cookie。这样也可以降低你的安全风险。
    
    在django中怎么去用呢
    
    对cookie操作,无非就是增加,删除,获取这些,我们在HttpResponse这个对象中操作
    那么,我能不能操作 render redirect JsonResponse这些呢?
    答案是可以的,上面的最终都是返回的是HttpResponse对象
    
    obj = HttpResponse('ok')
    obj.set_cookie()  #cookie是一个键值对,
    源码:
        set_cookie(self, key, value='', max_age=None, expires=None, path='/',
                   domain=None, secure=False, httponly=False):
    
    上面这个set_cookie的源码,key,value这两个参数不用讲了把,对应的键值对的两个值
    max_age ---->  代表过期时间,是None的话,cookie会保持到浏览器关闭,以s最为单位
    expires=None ----> 传一个时间对象过去,也是代表过期时间
    path='/'---->  代表cookie生效的路径,'/'代表该服务器中的所有路由都能生效,都会携带上
    domain=None ---->  cookie生效的域名
    secure=False ---->  浏览器将通过https来回传cookie
    httponly=False ---->  只能http协议传输,无法被JavaScript获取
    
    # 其实记得话只需记得过期时间,和前面那两个参数,一个key,一个value
    
    obj.set_signed_cookie
    源码:
        def set_signed_cookie(self, key, value, salt='', **kwargs):
            value = signing.get_cookie_signer(salt=key + salt).sign(value)
            return self.set_cookie(key, value, **kwargs)
    
    # 这是也是添加cookie的方式,它最终还是调了set_cookie方法,在set_cookie基础上又加了些操作
    # set_signed_cookie里又这样一个参数salt,相当于加个暗号,让你的cookie更加安全点
    # 这个是不是和设置hash值差不多。
    
    
    删除cookie操作:
    delete_cookie    你只需要传一个key值就行了
    源码:
        def delete_cookie(self, key, path='/', domain=None):
            self.set_cookie(key, max_age=0, path=path, domain=domain,
                            expires='Thu, 01-Jan-1970 00:00:00 GMT')
    
    你看,它最终还是执行了set_cookie,只不过它把max_age设置为0
    
    
    获取到cookie值:
    你请求的所携带的数据都在request对象中,所以这个cookie也不例外
    
    方式一:cookie1 = request.COOKIES
    
    方式二:cookie2 =request.META.get('HTTP_COOKIE')
    
    
    cookie1它的返回值是一个字典
    {'sessionid': 'j17hk7jxd4excy1efmisirfv4bbjpcdu'}
    
    cookie2它就是一个字符串了,
    request.COOKIES其本质就是通过cookie2的值进行字符串操作,得到的字典
    sessionid=j17hk7jxd4excy1efmisirfv4bbjpcdu
    
    # 用的话直接用request.COOKIES获取cookie值就行
    
    总结下cookie:1、它是保存在浏览器中的键值对
                 2、查看cookie,通过request.COOKIES,它是一个字典,取值就是字典取值了
                 3、set_cookie()和set_signed_cookie(),记住它是HttpResponse的方法

     二、session

    上面的讲的cookie很好的解决了保持会话的效果,但是毕竟还是有限,它保存在浏览器上对吧,那么用户就可以看到,
    其他人也有机会切取到账号密码,所以对用户来说存在一定的安全隐患的,所以必须要有新的保持会话的方式,所以
    session这种方式,很好的解决了这个问题,将数据保存在服务端上,外人不容易窃取到,况且还是加密保存的
    
    在django怎么去设置session呢?
    
    request.session['name'] = 'zhuyu'
    # 这一行代码进行了下面几个操作:
        1、首先生成了一个随机的字符串,这个字符串代表这这个浏览器的id
        2、然后设置一个给这个浏览器设置一个cookie key为sessionid,
           value就是{'name':'zhuyu'}这个字典所通过加密得到的字符串,
           相当于执行HttpResponse.set_cookie('sessionid',字典加密后的字符串)
        3、然后保存到数据库中,这个表名为django_session
    这样一个浏览器就有了一个唯一的id,作为cookie的value值
    
    那我在上面那行代码继续执行一行代码
    request.session['age'] = '21'
    那django会进行怎么的操作呢?是继续执行下面那三个操作?
    分析下:1、这是不是同一个浏览器发过去的数据,那么这个随机字符串上面是不是已经生成了
           2、基于1的想法,所以这个cookie是不是没有发生变化,现在主要是考虑这个字典加密后的字符串了
           3、你觉得是生成一个新的加密字符串覆盖直接旧的?还是{'name':'zhuyu','age':'21'}生成
              一个随机字符串再覆盖掉之前的?
           4、如果是基于3的想法一,生成一个字典加密的字符串覆盖掉之前的?那么你的session永远就是一个值?
              你觉得这样好吗?后面我们可以要通过这个加密后的字符串,反解密得到字典,再从数据库中,拿到
              该用户的信息,再返回到前台页面,那如果你的判断调节就一个name,就一个age,是根本不能确定
              是哪个用户的
           5、那应该就是组成一个大的字典,然后对字典进行加密操作,再保存到数据库中。
    
    额额,上面这个这是我yy的,你如果知道的话,可以再下面留言,不过应该每人看的,还是让我一个人在这里yy吧,哈哈
    
    request.session  这是一个对象,不是字典,他重写了__getitem__,__setitem__这两个方法
                     你可以把他当作一个字典去使用,get取值都行
    
    {'name':'zhuyu','age':'21'}
    request.session  相当于就是个字典,那么字典的一些方法,你可以使用
    
    取值的话:request.session['name']
             request.session.get('name')
    
    设置session数据: request.session['sex'] = ''
                     request.session.setdefault('name','朱宇')
                     # 意思是假如有name这个key,那就不赋值,没有的话添加{'name':'朱宇'}
    
    删除其中的一个key值:del request.session['sex']
                       你可以去试试pop行不行
    
    返回值是列表:
        request.session.keys()
        request.session.values()
        request.session.items()
    迭代器,每次返回一个数据:
        request.session.iteritems()
        request.session.iterkeys()
        request.session.itervalues()
    
    cookie_value = request.COOKIES.get('sessionid')
    request.session.exists(cookie_value)
    # 判断sessionid对应的值,在不在django_session表的session_key中,
    # 假如浏览器的cookie中没有sessionid,所以cookie_value为None,
    # 判断就为false。
    
    # 两种删除session的方式
    方式一:
      request.session.delete()  #这是删除整个session,删除的是那条记录
                                #但是浏览器的cookie是不会删掉的
    
      那你下次浏览再带这个cookie请求,
      request.session.exists(cookie_value)的值就为false了,因为数据库中查询不到
    
    方式二:
      request.session.flush()  # 删除数据库中的session,也删除了浏览器的cookie
      # 你想想它是怎么实现的?
      # 不就是执行request.session.delete(),再执行delete_cookie,就是这样吧

    三、在django的setting中配置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,默认修改之后才保存(默认)
    四、基于FBV和CBV加上session装饰器
    之前写过了,我就粘贴了
    
    基于FBV:
    def login_auth(func):
        def inner(request, *args, **kwargs):
            url = request.get_full_path()
            cook = request.COOKIES.get('sessionid')
            if request.session.exists(cook):
                return func(request, *args, **kwargs)
            else:
                return redirect('/login/?next_url=%s' % url)
    
        return inner
    # 假如你没有登陆的话,访问订单页面肯定是访问不了,所以让你先去登陆,登陆成功自动跳转到订单页面
    
    def login(request):
        print(request.session.set_expiry)
        if request.method == 'GET':
            return render(request, 'login.html')
        if request.method == 'POST':
            import json
            dic = json.loads(str(request.body, encoding='utf-8'))
            name = dic.get('name')
            pwd = dic.get('pwd')
            user = models.User.objects.filter(name=name, pwd=pwd)
            if user:
                request.session['name'] = name
                request.session['pwd'] = pwd
                path = request.GET.get('next_url')
                if path:
                    url = path
                else:
                    url = '/index/'
                new_dic = {'status': '100', 'info': url}
    
            else:
                new_dic = {'status': '200', 'info': '用户名或密码错误'}
            return JsonResponse(new_dic)
    
    @login_auth
    def order(request):
        return render(request, 'order.html')
    
    
    基于CBV:
    
    class Buy_cart(views.View):
        def get(self, request):
            return HttpResponse('get')
    
        def post(self, request):
            return HttpResponse('post')
    
        @method_decorator(login_auth)
        def dispatch(self, request, *args, **kwargs):
            return super().dispatch(request, *args, **kwargs)
    
    # 装饰器在上面
    ## 今天就到这里!!
    ## 提醒下,你要练习cookie,session的话,记得清理下浏览器的cookie,好了,没事了
     
  • 相关阅读:
    阿里巴巴2018秋招面经之前端岗(1~5面)
    面试分享:2018阿里巴巴前端面试总结(题目+答案 30题)
    2018年各大互联网前端面试题三(阿里)
    阿里巴巴2016前端工程师面试题
    2016 阿里校招笔试前端题目,你还记得吗?
    2018阿里前端校招分享(笔试篇)
    2017 阿里校招前端笔试题小结
    阿里2018校招编程题
    ko.js学习一
    简单的3d变换
  • 原文地址:https://www.cnblogs.com/zhuchunyu/p/10004391.html
Copyright © 2011-2022 走看看