【Django】cookie和session

cookie和session

参考:https://www.cnblogs.com/yuanchenqi/articles/5716193.html

通俗理解cookie:

浏览器访问服务器的网站时,进入登录界面 登录成功,服务器发给浏览器一个cookie,浏览器将cookie保存在本地磁盘上。当浏览器再访问该网站的页面(如购物车)时发送的request请求会携带cookie 服务器识别到请求的cookie与自己数据库中cookie相同 则允许用户继续访问,否则会自动跳到登录页面。

详细解释cookie和session

1、cookie不属于http协议范围,由于http协议无法保持状态,但实际情况,我们却又需要“保持状态”,因此cookie就是在这样一个场景下诞生。

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

2、cookie虽然在一定程度上解决了“保持状态”的需求,但是由于cookie本身最大支持4096字节(约4Kb),以及cookie本身保存在客户端,可能被拦截或窃取,因此就需要有一种新的东西,它能支持更多的字节,并且他保存在服务器,有较高的安全性。这就是session。

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

我们可以给每个客户端的cookie分配一个唯一的id,这样用户在访问时,通过cookie,服务器就知道来的人是“谁”。然后我们再根据不同的cookie的id,在服务器上保存一段时间的私密资料,如“账号密码”等等。

3、总结而言:cookie弥补了http无状态的不足,让服务器知道来的人是“谁”;但是cookie以文本的形式保存在本地,自身安全性较差;所以我们就通过cookie识别不同的用户,对应的在session里保存私密的信息以及超过4096字节的文本。

4、另外,上述所说的cookie和session其实是共通性的东西,不限于语言和框架

前几节的介绍中我们已经有能力制作一个登陆页面,在验证了用户名和密码的正确性后跳转到后台的页面。但是测试后也发现,如果绕过登陆页面。直接输入后台的url地址也可以直接访问的。这个显然是不合理的。其实我们缺失的就是cookie和session配合的验证。有了这个验证过程,我们就可以实现和其他网站一样必须登录才能进入后台页面了。

      先说一下这种认证的机制。每当我们使用一款浏览器访问一个登陆页面的时候,一旦我们通过了认证。服务器端就会发送一组随机唯一的字符串(假设是123abc)到浏览器端,这个被存储在浏览端的东西就叫cookie。而服务器端也会自己存储一下用户当前的状态,比如login=true,username=hahaha之类的用户信息。但是这种存储是以字典形式存储的,字典的唯一key就是刚才发给用户的唯一的cookie值。那么如果在服务器端查看session信息的话,理论上就会看到如下样子的字典

{'123abc':{'login':true,'username:hahaha'}}

因为每个cookie都是唯一的,所以我们在电脑上换个浏览器再登陆同一个网站也需要再次验证。那么为什么说我们只是理论上看到这样子的字典呢?因为处于安全性的考虑,其实对于上面那个大字典不光key值123abc是被加密的,value值{'login':true,'username:hahaha'}在服务器端也是一样被加密的。所以我们服务器上就算打开session信息看到的也是类似与以下样子的东西   {'123abc':dasdasdasd1231231da1231231}
View Code

Django中的cookie

Django默认发送的cookie格式为:

{'csrftoken': 'zPglXV38MGIn3znrQ6JHNhz4UsWZ65SoGInzOnDVYrshlLjVpZz8cpsrlgwxij4p', 'sessionid': 'hb60ns6r1pe8bl805x7wxnsocekz3so5'}

借用一张别的大神画的图,可以更直观的看出来cookie和session的关系:

wKioL1bmwJqQWT79AACFVu-rqIs465.gif

   

    知道了原理,我们下面就来用代码实现

先在templates目录下创建两个html,login.html负责登录页面。index页面代表用户个人首页

views.py

from django.shortcuts import render,HttpResponse,redirect
import datetime

def login(request):
    print("COOKIES",request.COOKIES)
    print("session",request.session)

    if request.method =="POST":
        name = request.POST.get("user")
        pwd = request.POST.get("pwd")
        if name =="xiong" and pwd == "123456":
        #     ret = redirect("/index/")
        #     # max_age 和 expires都是设置cookie有效时间,一般情况下两者要设置相同
        #     ret.set_cookie("usernameis","xiongxiong",max_age=8)   #组成键值对
        #     return ret

            # cookie +session 写法
            request.session["is_login"] = True
            request.session["user"] = name
            return redirect("/index/")

    return render(request,"login.html")

def index(request):
    ## request.COOKIES.get("usernameis", None)  取cookies中键名为usernameis 的值,取不到默认为空,如果不写None 取不到会报错
    # if request.COOKIES.get("usernameis",None) == "xiongxiong":
    #     name = request.COOKIES.get("usernameis",None)
    #     return render(request,"index.html",locals())

    if request.session.get("is_login",None):
        print(request.session)
        print(request.session["user"])
        name = request.session.get("user",None)
        return render(request,"index.html",locals())

    return redirect("/login/")

参考视图函数views.py 写法:

# /usr/bin/env python
# coding:utf-8
from django.shortcuts import render
from django.shortcuts import redirect
def login(request):
    if request.method=="POST":
        username=request.POST['username']
        pwd=request.POST['passwd']
        if username=='abc' and pwd=='123':
            #设置session内部的字典内容
            request.session['is_login']='true'
            request.session['username']='abc'
            #登录成功就将url重定向到后台的url
            return redirect('/backend/')
    #登录不成功或第一访问就停留在登录页面
    return render(request,'login.html')
def backend(request):
    """
    这里必须用读取字典的get()方法把is_login的value缺省设置为False,
    当用户访问backend这个url先尝试获取这个浏览器对应的session中的
    is_login的值。如果对方登录成功的话,在login里就已经把is_login
    的值修改为了True,反之这个值就是False的
    """
    is_login=request.session.get('is_login',False)
    #如果为真,就说明用户是正常登陆的
    if is_login:
        #获取字典的内容并传入页面文件
        cookie_content=request.COOKIES
        session_content=request.session
        username=request.session['username']
        return render(request,'backend.html',
                      {
            'cookie_content':cookie_content,
            'session_content':session_content,
            'username':username
                      })
    else:
        """
        如果访问的时候没有携带正确的session,
        就直接被重定向url回login页面
        """
        return redirect('/login/')
def logout(request):
    """
    直接通过request.session['is_login']回去返回的时候,
    如果is_login对应的value值不存在会导致程序异常。所以
    需要做异常处理
    """
    try:
        #删除is_login对应的value值
        del request.session['is_login']
    except KeyError:
        pass
    #点击注销之后,直接重定向回登录页面
    return redirect('/login/')
参考yuan先生博客

login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>个人首页</title>
</head>
<body>
<form action="/login/" method="post">
    <p>用户名:<input type="text" name="user" placeholder="用户名"></p>
    <p>密码:<input type="text" name="pwd" placeholder="密码"></p>
    <p><input type="submit" value="提交"></p>
</form>
</body>
</html>
login.html

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登录页面</title>
</head>
<body>
<h2>登录成功-用户名为:{{ name }}</h2>
</body>
</html>
index.html

只有在输入了正确的用户名和密码之后才进入到了/backend/页面

wKiom1bm4UOjEwzlAAE9se9_78U441.png

从上图中我们看到有一下几点:

1、login页面正确登录的话,后台页面可以获取到浏览器携带的cookie的。

2、第一行的sessionid其实就是cookie值

3、session的内容是加密的,从客户端获取不到session的内容

4、服务端可以通过预设的key值取出session的内容并打印到前段

从火狐浏览器里查看cookie

wKioL1bm5aLicB3pAAC_XkZOUds501.png

django的session默认是存储在数据库里的,我们再到数据库查看一下真正session内容

---> session的工作流程:

wKiom1bm6EHiV1i0AADUm8yxkhs649.png

最后我们再来最后的总结一下cookie和session的知识点:

一、操作Cookie

  获取cookie:request.COOKIES[key]

  设置cookie:response.set_cookie(key,value)

由于cookie保存在客户端的电脑上,所以,jquery也可以操作cookie。

<script src='http://830909.blog.51cto.com/static/js/jquery.cookie.js'></script>
$.cookie("list_pager_num", 30,{ path: '/' });

二、操作Session(session默认在服务器端保存15天)

  获取session:request.session[key]

  设置session:reqeust.session[key] = value

  删除session:del request.session[key]    

(这个删除其实就是把数据库的session_data更新为一个其他的值了,并没有立即删除)

request.session.set_expiry(value)
* 如果value是个整数,session会在些秒数后失效。
* 如果value是个datatime或timedelta,session就会在这个时间后失效。
* 如果value是0,用户关闭浏览器session就会失效。
* 如果value是None,session会依赖全局session失效策略。

可以设置失效cookie天数

ret = redirect("/index/")
        #     # max_age 和 expires都是设置cookie有效时间,一般情况下两者要设置相同
        #     ret.set_cookie("usernameis","xiongxiong",max_age=8)   #usernameis和xiongxiong组成cookies键值对,max_age=8 8秒后cookie失效
            ret.set_cookie("usernameis","xiongxiong",expires=datetime.datetime.utcnow()+datetime.timedelta(days=3))   #组成键值对

 

posted @ 2019-08-08 10:55  XJT2019  阅读(139)  评论(0编辑  收藏  举报