彻底明白在flask框架下使用session是怎么和cookie相配合来解析用户登录状态等数据信息的

cookie和session结合使用:web开发发展至今,cookie和session的使用已经出现了一些非常成熟的方案。

session的两种存储方式

如今的市场或者企业里,一般有两种存储方式:

  1. 存储在服务端:通过cookie存储一个session_id,然后具体的数据则是保存在session中。如果用户已经登录,则服务器会在cookie中保存一个session_id,下次再次请求的时候,会把该session_id携带上来,服务器根据session_id在session库中获取用户的session数据。就能知道该用户到底是谁,以及之前保存的一些状态信息。这种专业术语叫做server side session。
  2. 将session数据加密,然后存储在cookie中。这种专业术语叫做client side session。flask采用的就是这种方式,但是也可以替换成其他形式。

从浏览器发送请求到服务器返回响应的过程分析flask 是如何通过cookie和session机制实现用户是否登录的

Flask中的session是通过from flask import session。然后添加值key和value进去即可。并且,Flask中的session机制是将session信息加密,然后存储在cookie中。专业术语叫做client side session。其具体实现步骤如下:

  1. 设置秘钥
  2. 设置过期时间 也可以不设置
  3. 在用户首次登录成功后以key-value的方式向session中添加数据,比如加入session【‘username’】 = username
  4. 根据秘钥和加密算法将session数据进行加密
  5. 将加密后的session数据添加到response中,保存在set-cookie 字段中
  6. 浏览器接受到服务器返回的消息,通过解析response header中的set-cookie字段,自动将cookie信息保存在浏览器中。
  7. 当用户再次在同一浏览器,同一域名下发送请求时,浏览器会将cookie自动添加在request header的cookie字段中。
  8. 服务器获取到request header中的cookie数据,判断其是否失效,如果没有失效则按照算法对其解密,如果cookie数据中途被修改过,则会导致解密失败,该cookie将会直接被丢弃,如果解析cookie成功,则可以将session中的key-value键值对解析出来,然后可以通过判断该键值对中是否有key== ‘username’的字段,如果有说明用户已经登录,如果没有说明用户没有登录。
细节介绍

上述过程涉及到加密算法,秘钥生成等细节,下面对这些细节详细介绍下:

Flask生成生成动态秘钥SECRET_KEY并设置秘钥

import os
# Set the secret key to some random bytes. Keep this really secret!
app.secret_key = os.urandom(24)
'\xca\x0c\x86\x04\x98@\x02b\x1b7\x8c\x88]\x1b\xd7"+\xe6px@\xc3#\\'

给session赋值

@app.route('/login/', methods=['GET', 'POST'])
def login():
    # 如果是登录 验证用户名密码则 进入 post
    if request.method == 'POST':
        if not request.form.has_key('username') or not request.form.has_key('password') or request.form["username"] == "":
            return returnInfo(0, '参数异常:缺少参数')
        password = request.form['password']
        username = request.form['username']
        login_time = int(time.time())
        user = User(username, password, login_time, db)
        result = user.check_user_can_logged()
        if result['status']:
            session['username'] = username
        return json.dumps(result)
    # 加载登录页面 get 请求
    return render_template('login.html')

获取session的值

@app.before_request
def filter_url():
    # 如果用户未登录,则跳转到用户登录界面 登录请求和请求静态资源除外
    if 'username' not in session and request.path != url_for('login') and request.path.find('/static/') == -1:
        return redirect(url_for('login'))

如何删除session数据
删除一个:session.pop(“key”,none),例如上述案例中为:session.pop(“username”,none)
删除所有:session.clear()

源码分析

在获取 cookie 数据的过程中,最核心的几句话是:

s = self.get_signing_serializer(app)
val = request.cookies.get(app.session_cookie_name)
data = s.loads(val, max_age=max_age)
 
return self.session_class(data)

其中两句都和 s 有关,signing_serializer 保证了 cookie 和 session 的转换过程中的安全问题。如果 flask 发现请求的 cookie 被篡改了,它会直接放弃使用。

我们继续看 get_signing_serializer 方法:

def get_signing_serializer(self, app):
    if not app.secret_key:
        return None
    signer_kwargs = dict(
        key_derivation=self.key_derivation,
        digest_method=self.digest_method
    )
    return URLSafeTimedSerializer(app.secret_key,
        salt=self.salt,
        serializer=self.serializer,
        signer_kwargs=signer_kwargs)

我们看到这里需要用到很多参数:

  1. secret_key:密钥。这个是必须的,如果没有配置 secret_key 就直接使用 session 会报错
  2. salt:为了增强安全性而设置一个 salt 字符串(可以自行搜索“安全加盐”了解对应的原理)
  3. serializer:序列算法
  4. signer_kwargs:其他参数,包括摘要/hash算法(默认是 sha1)和 签名算法(默认是 hmac)

URLSafeTimedSerializer 是 itsdangerous 库的类,主要用来进行数据验证,增加网络中数据的安全性。itsdangerours提供了多种 Serializer,可以方便地进行类似 json 处理的数据序列化和反序列的操作。至于具体的实现,因为篇幅限制,就不解释了。

参考文档

flask中的session设置
flask学习笔记–flask内置session处理机制

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值