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,好了,没事了
 

猜你喜欢

转载自www.cnblogs.com/zhuchunyu/p/10004391.html