cookie和session的那些事

对于常常网购的朋友来讲,常常会遇到一种状况:
打开淘宝或京东商城的首页,输入我的帐号和密码进行登录,而后进行购物,支付等操做都不须要用户再次输入用户名和密码
可是若是用户换一个浏览器或者等几个小时后再刷新这些网页进行购物操做,就必需要再次输入用户名和密码了.html

这是为何呢??这就用到了cookiesession的知识了.python

1. cookie的简介

一、http是无状态协议,cookie不属于http协议范围.

在实际应用中,服务端与客户端须要保持链接状态,此时就须要使用到cookie.web

cookie的工做原理是:由服务器产生客户端身份信息发送给客户端,客户端收到信息后保存在本地;
当客户端浏览器再次访问服务端时,会自动带上这段身份信息,服务器经过这段信息来判断客户端的身份。chrome

打开chrome浏览器,在地址栏里输入www.cnblogs.com,回车在检查中能够的信息以下图所示:数据库

其中,能够看到这次的请求头(Request Headers):django

Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding:gzip, deflate, br
Accept-Language:zh-CN,zh;q=0.8
Cache-Control:max-age=0
Connection:keep-alive
Cookie:__gads=ID=ec125291e23201fe:T=1504664243:S=ALNI_MZTHHsRs1K2HAD8kB_Q7zN777zCMA
Host:www.cnblogs.com
If-Modified-Since:Sat, 09 Sep 2017 12:38:59 GMT
Upgrade-Insecure-Requests:1
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36

在这些信息里,能够看到cookie信息是包含在请求头里的.
浏览器发请求的时候,会从浏览器中取出cookie附加到请求头上,给服务端发过去.服务端接收到客户端的cookie以后,会给客户端返回相应的信息.后端

还能够看到服务端的响应头(Response Headers):浏览器

Cache-Control:public, max-age=19
Connection:keep-alive
Content-Encoding:gzip
Content-Type:text/html; charset=utf-8 
Date:Sat, 09 Sep 2017 12:42:16 GMT
Expires:Sat, 09 Sep 2017 12:42:36 GMT
Last-Modified:Sat, 09 Sep 2017 12:42:06 GMT
Transfer-Encoding:chunked
Vary:Accept-Encoding
X-Frame-Options:SAMEORIGIN
X-UA-Compatible:IE=10

二、cookie在必定程度上解决了"保持状态"的需求

因为cookie自己最大支持4096字节,而且cookie保存在客户端,可能被拦截或窃取,
所以须要有一种新的东西,它来弥补cookie的一些缺陷,而且保存在服务端,有较高的安全性,这就是session。安全

基于http协议的无状态特征,服务器不知道访问者的身份,此时cookie就起到桥接的做用。服务器

服务端给每一个客户端的cookie分配一个惟一的随机id,用户在访问服务端时,服务器经过cookie来判断客户端的身份。

服务端根据cookie的id的不一样,在必定的期限内保存客户端传送过来的帐号密码等关键信息.

三、cookie弥补了http无状态的不足,让服务器可以判断客户端的身份;

cookie以文本的形式保存在本地,自身安全性较差,所以服务端经过cookie识别不一样的用户,对应的在session里保存私密的信息以及超过4096字节的文本。

四、cookie和session实际上是共通性的东西,不限于语言和框架

2.cookie和session的工做机制

每当咱们使用一款浏览器访问一个登录页面的时候,一旦咱们经过了认证,服务器端就会发送一组随机惟一的字符串(假设是123abc)到浏览器端.
这个被存储在浏览器端的东西就叫cookie。而服务器端也会存储一下用户当前的状态,好比login=trueusername="name"之类的用户信息。
这种信息是以字典形式存储成为一个字符串,这串字符串以用户第一次请求时获得的cookie值为键,这就是session.

那么若是在服务器端查看session信息的话,理论上就会看到以下样子的相似的字典
{'123abc':{'login':true,'username':'hahaha'}}

由于每一个cookie都是惟一随机的,因此咱们在同一台电脑上换个浏览器再登录同一个网站也须要再次验证。

那么为何说咱们只是理论上看到这样子相似的字典呢?由于处于安全性的考虑,其键和值在服务器端都会被加密。

因此咱们服务器上就算打开session信息看到的也是相似与如下样子的东西:

{'123abc':dasdasdasd1231231da1231231}

3.cookie和session的初步使用

例子:制做一个登录页面,服务端使用cookie和session验证了用户名和密码后才能跳转到后台的页面。

3.1 首先建立一个Django的项目,配置好urls和settings,templates中建立一个login.html和index.html页面

views中的代码:

def index(request):
    return render(request,"index.html")

def login(request):
    print("cookie:",request.COOKIES)#打印cookie信息
    if request.method=="POST":#若是浏览器使用post方式提交信息
        name=request.POST.get("username")
        pwd=request.POST.get("password")
        if name=="hello" and pwd=="123456":
            return redirect("/index/")

    return render(request,"login.html")

login页面:

<form action="/login/" method="post">
    <p>姓名<input type="text" name="username"></p>
    <p>密码<input type="password" name="password"></p>
    <p><input type="submit"></p>
</form>

index页面:

<h3>welcome to index page</h3>

打开浏览器,输入http://127.0.0.1:8000/login/打开login页面,输入正确的用户名和密码,进入index页面
此时能够在后端看到以下的cookie信息

cookie: {'csrftoken': 'AdkajMM65wOqa0NONe6dVwYqphGNDOgMbuzstmAy92HJ3GxRWUNpqXKJFXBv1Rn5', 
'sessionid': '7jfj6uqbz6vylplfv429bhfdxh14iwfp'}

其中sessionid中的信息就是Django分配给浏览器的一段随机字符串.

3.2 由用户本身设置cookie信息

修改login视图函数:

def login(request):
    print("cookie:",request.COOKIES)
    if request.method=="POST":
        name=request.POST.get("username")
        pwd=request.POST.get("password")
        if name=="hello" and pwd=="123456":
            res=redirect("/index/")
            res.set_cookie("login_message","hello python")#设置cookie信息
            return res
    return render(request,"login.html")

而后重启应用,从新输入用户名和密码,进入index页面,此时能够看到以下的cookie信息:

cookie: {'csrftoken': 'AdkajMM65wOqa0NONe6dVwYqphGNDOgMbuzstmAy92HJ3GxRWUNpqXKJFXBv1Rn5', 
'sessionid': '7jfj6uqbz6vylplfv429bhfdxh14iwfp', 'login_message': 'hello python'}

能够看到在后端的login视图函数中设置的cookie的键值对,浏览器请求后又会被服务端接收.

用户请求页面时,是带着标示本身的身份信息的,服务端对客户端的身份信息进行判断,只有身份正确,才能进入index页面.
可是若是在浏览器的地址中直接输入index的路由地址,也能进入index的页面的状况,这不符合咱们的要求.

3.3 实现客户端没有cookie,即便用户输入index路由信息,服务端发送登陆页面给用户

若是客户端没有cookie,说明用户名或密码没有验证成功,服务端就会把login页面发送给客户端浏览器,
只有用户输入正确的用户名和密码,服务端才会把index页面发送给客户端浏览器.

修改index视图函数:

def index(request):
    if request.COOKIES.get("login_message")=="hello python":
        return render(request,"index.html",locals())
    else:
        return redirect("/login/")

这样用户在一个浏览器中通过验证进入index.html页面后,清除cookie或者更换一个浏览器再想进入index页面,就要再次验证用户名和密码了.

因为用户的cookie信息保存在客户端,每与服务端通讯一次,客户端就要把cookie信息发送经服务端一次,并且保存在客户端也不够安全,因此又出现了session
session也保存客户端身份的信息,用户登陆后服务端把表示用户身份的信息保存成以键值对形式存在的session中,而后服务端把这个字典发送给客户端的cookie,

这时客户端的cookie就以一个字符串的形式存在.

客户端使用cookie和session与服务端进行通讯的步骤:

用户通过用户名和密码验证登录后,生成一个字典,将字典存入session,session的key是自动生成一段字符串标识,也就是前面说过的cookie.
服务端返回给客户端session,session的value存储了用户的关键信息,如user和iflogin等.

在Django中用到session时,cookie由服务端随机生成,写到浏览器的cookie中,每一个浏览器都有本身的cookie值,是session寻找用户信息的惟一标识

每一个浏览器请求到后台接收的request,这时的session等价于标识用户身份信息的字典

3.4 使用cookie加session来完成上面的例子

修改views中的login视图函数

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

    if request.method=="POST":
        name=request.POST.get("username")
        pwd=request.POST.get("password")
        if name=="hello" and pwd=="123456":

            res=redirect("/index/")
            res.set_cookie("login_message","hello python")
            return res

    return render(request,"login.html")

再次刷新浏览器,输入正确的用户名和密码后,打印cookie和session:

cookie: {'csrftoken': 'AdkajMM65wOqa0NONe6dVwYqphGNDOgMbuzstmAy92HJ3GxRWUNpqXKJFXBv1Rn5', 
'sessionid': '7jfj6uqbz6vylplfv429bhfdxh14iwfp', 'login_message': 'hello python'}

session: <django.contrib.sessions.backends.db.SessionStore object at 0x00000000043D7D30>

能够看到的是此时的session是一个对象.

知道了cookie和session的状况后,那么该怎么使用cookie和session呢

修改视图函数

def index(request):
    if request.session.get("is_login",None):#获取session中用户登陆的信息
        name=request.session.get("user")#获取session中的用户名
        return render(request,"index.html",locals())
    else:
        return redirect("/login/")

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

    if request.method=="POST":
        name=request.POST.get("username")
        pwd=request.POST.get("password")
        
        if name=="hello" and pwd=="123456":
            request.session["is_login"]=True
            request.session["user"]=name
            return redirect("/index/")
    return render(request,"login.html")

先使用

python manage.py makemigrations
python manage.py migrate

命令初始化数据库,
而后在浏览器中输入http://127.0.0.1:8000/index/后,直接进入登陆页面了,输入正确的用户名和密码,后端会打印以下信息:

cookie: {}
session: <django.contrib.sessions.backends.db.SessionStore object at 0x00000000043B46D8>

4 cookie和session的用法:

4.1 操做cookie

获取cookie            request.COOKIE[key]
设置cookie            response.set_cookie(key,value)

因为cookie保存在客户端的电脑上,因此jQuery也能够操做cookie

在上面的例子中,在html页面中就使用Django的语法能够渲染name变量.

设置cookie的失效时间:

import datetime#导入datetime模块

response.set_cookie("username",{"11":"22"},max_age=10,
    expires=datetime.datetime.utcnow()+datetime.timedelta(days=3))

其中:

datetime.datetime.utcnow()表示当前时间
datetime.timedelta(days=3)表示3天

上面的代码表示设置cookie在当前时间的3天后失效

4.2 操做session(session默认在服务端保存15天)

获取session       request.session[key]或者request.session.get(key)
设置session       request.session[key]=value
删除session       del request.session[key]

须要注意的是,删除服务端的session不会删除数据库中的session_data,而只是把session更新为一个其余的值

设置session的失效时间:

request.session.set_expiry(value)是设置session的失效时间

参数说明:

若是value是一个整数,session会在整数称后失效
若是value是个datatime或者timedelta,session会在这个时间以后失效
若是value是0,用户关闭浏览器后session就会失效
若是value是None,session会依赖全局session的失效策略
相关文章
相关标签/搜索