cookie技术的必要性
今天来讲一个在现今web应用中,最最基础和最最重要的技术点,几乎没有他们就无法促成web技术的推广和应用,他们就是cookie和session一对孪生兄弟。先说一下他们诞生和存在的必要性。
我们在浏览网站的时候,访问每一个页面都需要使用“http协议”来实现。而http协议是无状态的协议,就是说http协议没有一个内部的机制来维护两次请求之间的状态保持。比如说当一个用户请求同一个网站的A页面后,再请求B页面,http协议不能告诉服务器这两次请求是来自于同一个用户。而是会把两次请求当做独立的请求。而要让网站能记住多次请求来自同一个用户的这种需求在网站开发中是非常必需的技术。下面举一个我们经常用到的网站的功能你就能明白为什么需要这种技术了。
比如我们在网上购物的时候,往往会添加多个商品到自己的购物车当中,每添加一件商品就是一次请求,那么为了使得我们多次添加购物车的动作都能放到同一个用户的名下,是不是需要保证多个请求的请求来自于同一个用户?所以对这一技术的强烈需求就诞生了cookie技术。
cookie的实现原理
cookie可以将用户信息比如用户id保存到浏览器当中的cookie里面,cookie是一个类似缓存的东西,当用户通过验证之后服务器就会将用户的id保存到cookie里面,当用户请求不同页面的时候都会携带着用户的id,如果进行添加购物车的动作的话,那么多个商品都会放到此用户id下面,当用户需要下单的时候程序就会通过此id对应找到数据库里面的此用户的记录,生成一条此用户id的订单记录。这样就能实现不同页面跳转的时候唯一确定用户身份了。
打个比较容易理解的比喻:如果把服务器比作一家商场,商场中的每个店面比做一个页面,而cookie好比你第一次去商场时,经过你提供用户信息之后,由商场为你提供的一张会员卡。当你在这家商场的任何店面中购物时,只要你提供由你保存的会员卡,就会被看做商场的会员。你在此商城所有店面所购买的所有商品都会放到你的会员名下。
cookie原理示意图:
flask是如何实现和应用cookie技术的
首先肯定是保存cookie,保存cookie这个动作一般是用在登录的时候,那么下面就让我们写一个模拟登录的视图函数login
,由于现在还不涉及和数据库的验证交互,所以就不进行验证,就算验证通过了,然后直接写入cookie
# 顶部引入make_response
from flask import Flask, make_response
@app.route('/login')
def login():
response = make_response('登录成功!') # 实例化响应对象
response.set_cookie('username', 'xiaoming') # 通过相应对象的set_cookie方法设置cookie,
# cookie信息是一个键值对形式的数据,以cookie形式进行保存
return response
这里需要用到相应对象make_response,实例化之后,可以用它的一个方法set_cookie进行cookie信息的保存。保存之后返回响应结果。如果我们请求这个视图函数之后,键值对形式的username=xiaoming就被保存到了cookie当中了。我们可以通过检查元素的存储,再点击cookie查看保存的cookie信息。如果正常保存就可以看到保存的cookie信息。这样保存用户信息之后,当我们再次通过浏览器发起对服务器的请求的时候,浏览器就会自动带上此网站的cookie,由于cookie中保存的是用户信息,所以我们就可以以此来唯一确定用户身份了。就可以保持状态了。
登录之后,我们下一步就要验证看看我们是否可以从cookie当中拿到保存在cookie中的用户信息呢?如果能拿到,那么我们就可以进行展示出来,也就是我们经常在网站右上角看到的,登录之后显示的用户名等个人信息。那么下面我们再来创建一个登录信息的视图函数。
@app.route('/user_info')
def user_info():
return request.cookies.get('username', '用户信息不存在!')
以上代码就是通过上一节我们用到的request对象下面的cookies来拿到cookie当中保存的用户信息,如果找不到用户信息,则提示用户信息不存在。
现在已经模拟了登录和访问用户中心了,接下来就该退出了。退出的语法应该这样来写。
@app.route('/logout')
def logout():
response = make_response('退出成功!')
response.delete_cookie('username')
return response
这次依然用到了make_response对象的删除cookie的方法来清除cookie记录。cookie一旦被清除,那么在用户中心就获取不到用户信息了,就会输出用户信息不存在!
session的实现原理
sesion和cookie相似,都是用来存储用户信息的,最大的不同在于,cookie是将用户信息保存在客户端的计算机中,而session则是将用户的信息加密以后放到服务器的session当中,由于服务器上会保存很多用户的信息,所以要对各自的session信息进行编号,就类似在服务器放了很多盒子,每个盒子里面存放着一个用户的加密信息,那么每个盒子的编号我们这里用session_id来表示,服务器就会把这个session_id返回到客户端,客户端把这个session_id保存到cookie当中,下次再请求服务器的时候,会自动带上这个session_id由于每个人的session_id都是随机生成,而且是唯一的,所以就能唯一确定用户身份。还有就是,用户信息这次是加密之后保存在服务器端的,所以要比cookie更加安全。
对比我们在cookie中举得例子,可以这样来形容:如果用户去商场的时候忘记带会员卡了,但是他之需要提供卡号(session_id)就还是可以唯一确定用户身份的,因为会员卡号肯定是唯一的。
session实现原理示意图:
flask的session原理
上面讲的时常规的session原理,而flask框架在上面的基础之上,又做了一次封装,使得我们读取和使用session更加简单。flask是直接将加密之后的用户数据返回给了客户端,客户端再通过cookie进行保存,所以依然是让客户端保存用户信息,而不是返回盒子编码(session_id),这样,服务器就不用保持用户信息了,节省了服务器的开销。那么取session当中的用户信息也是可以直接取,就不用再经过session_id这个中间环节了。由于我们一直在强调是要把用户信息加密之后进行保存的,所以就需要设置一个SECRET_KEY,这个就相当于对我们的加密算法加盐,也就是加了我们自定义的干扰项,更进一步的保证数据的安全性。
由于flask这种封装,所以我们在操作session的时候就相当于操作session这个字典一样,所以关于登录、用户中心,退出这些功能的实现一并展示到下面统一为大家做解释。
@app.route('/login2')
def login2():
session['username'] = 'xiaohua'
return '登录成功!'
@app.route('/user_info2')
def user_info2():
return session.get('username', '用户信息不存在!')
@app.route('/logout2')
def logout2():
session.pop('username', None) # None参数保证不报错,也就是当pop找不到需要删除的下标的时候会返回None,从而使得不报错。
return '退出成功!'
flask实现session原理示意图:
对于登录就是往session字典当中加元素就可以了,加了之后就可以通过下标访问到用户的信息在用户中心进行展示输出,那么退出登录的时候可以通过键找到相应的键值对,一并弹出删除,如果不存在返回None,避免报错。