flask源码阅读笔记(2)-session相关

一、session的使用与常识

1.参考flask官方demo实现如下一段代码

# encoding: utf-8
"""
@version: 1.0
@author: pierrexiong
@file: my_session
@time: 2018/7/17 上午12:00
"""
from flask import Flask, session, redirect, url_for, escape, request

app = Flask(__name__)


@app.route('/')
def index():
    if 'username' in session:
        return 'Logged in as %s' % escape(session['username'])
    return 'You are not logged in'


@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        session['username'] = request.form['username']
        return redirect(url_for('index'))
    return '''
        <form action="" method="post">
            <p><input type=text name=username>
            <p><input type=submit value=Login>
        </form>
    '''


@app.route('/logout')
def logout():
    # remove the username from the session if it's there
    session.pop('username', None)
    return redirect(url_for('index'))


# set the secret key.  keep this really secret:
app.secret_key = 'A0Zr98j/3yX R~XHH!jmN]LWX/,?RT'

if __name__ == '__main__':
    app.run()

【图片一】

session1.jpg

基于代码可看出,flask的session是基于cookie实现的,这样可以实现不同请求间存储特定用户的信息,实现用户状态的保持。

当然flask对cookie的安全做了一些基础的加固:

  • cookie是httponly的,这样js就不能获取到,一定程度可以防范xss攻击。
  • cookie的值是可签名的(与app.secret_key的值相关 )。这意味着用户可以查看你 Cookie 的内容,但却不能修改它,除非用户知道签名的密钥。

二、实现原理和源码阅读

正如前文所说flask的session基于cookie实现,相关基础源码见sessions.py,核心安全部分是基于itsdangerous实现(http://itsdangerous.readthedocs.io/en/latest/)

# 生成session
    def save_session(self, app, session, response):
        domain = self.get_cookie_domain(app)
        path = self.get_cookie_path(app)

        # If the session is modified to be empty, remove the cookie.
        # If the session is empty, return without setting the cookie.
        if not session:
            if session.modified:
                response.delete_cookie(
                    app.session_cookie_name,
                    domain=domain,
                    path=path
                )

            return

        # Add a "Vary: Cookie" header if the session was accessed at all.
        if session.accessed:
            response.vary.add('Cookie')

        if not self.should_set_cookie(app, session):
            return

        httponly = self.get_cookie_httponly(app)
        secure = self.get_cookie_secure(app)
        samesite = self.get_cookie_samesite(app)
        expires = self.get_expiration_time(app, session)
        val = self.get_signing_serializer(app).dumps(dict(session))
        response.set_cookie(
            app.session_cookie_name,
            val,
            expires=expires,
            httponly=httponly,
            domain=domain,
            path=path,
            secure=secure,
            samesite=samesite
        )

如上述代码所示,我们使用save_session来生成并保存我们的session。其中不难看出,最终还是将下列值set到cookie里面:

  • cookie是否httponly
  • cookie的值,核心部分,使用到get_signing_serializer这个方法
  • cookie的domain
  • cookie的path
  • cookie的secure值:是否使用https传递cookie
  • cookie的samesite:同站问题
  • cookie的expires值:浏览器保存的周期
# 打开session并进行校验
    def open_session(self, app, request):
        s = self.get_signing_serializer(app)
        if s is None:
            return None
        val = request.cookies.get(app.session_cookie_name)
        if not val:
            return self.session_class()
        max_age = total_seconds(app.permanent_session_lifetime)
        try:
            data = s.loads(val, max_age=max_age)
            return self.session_class(data)
        except BadSignature:
            return self.session_class()

flask打开session时会读取cookie的val,并使用签名来验证是否有效

    salt = 'cookie-session'
    digest_method = staticmethod(hashlib.sha1)
    key_derivation = 'hmac'
    serializer = session_json_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)

在SecureCookieSessionInterface类中会使用上述方法生成签名, 其中URLSafeTimedSerializer就是来自itsdangerous。

一旦app.secret_key泄露,则整个session体系将变得不安全。

(后面有时间可以模拟因泄露secret_key而进行的web攻击)

其他

1.指定cookie的名字及配置:

app.session_cookie_name = 'flask_session'
# permanent_session_lifetime 设置session保持时间

2.session数据结构:字典(不细讲)

3.flask_login的安全加固

4.session在模板里面的作用

5.新版本推荐使用session_interface在操纵session

三、总结

flask官方的session实现,依然是俗套的方法:

  1. 将session的内容序列化到浏览器的cookie
  2. 浏览器再次请求时将反序列化cookie内容

flask在安全上的保证:

  1. cookie本身的一些安全防护(httponly等)
  2. 基于itsdangerous的签名:内容序列化+时间+防篡改值

四、参考

https://blog.csdn.net/yueguanghaidao/article/details/40016235

https://www.jianshu.com/p/9d8928cbb21d

原文链接:https://blog.csdn.net/u013128262

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏L宝宝聊IT

Squid代理服务器应用示例

5103
来自专栏编程坑太多

『高级篇』docker之微服务docker下的服务通讯(19)

1163
来自专栏xiaoxi666的专栏

配置多个git账号的ssh密钥

我们在工作中会以 ssh 的方式配置公司的 git 账号,但是平时也会使用 github 管理自己的项目。出于各种原因,自己的 github 项目无法使用公司的...

1902
来自专栏bboysoul

linux编译安装php

wget http://cn.php.net/distributions/php-7.1.1.tar.gz 去官网下载吧,香港那个地址第一个就是 tar -...

831
来自专栏LuckQI

linux进行硬盘分区挂载-了解系统,最更好的开发

我个人在操作linux分区的时候使用的是fdisk 命令 首先看下fdisk的命令学习下。使用fdisk --help 查看

1141
来自专栏Python

解决Nginx出现403 forbidden (13: Permission denied)报错的四种方法

我是在在本地用虚拟机中通过yum安装nginx的,安装一切正常,但是访问时报403,

2261
来自专栏Android相关

Linux--Zip命令

最近在弄打包的一些问题,由于其他部门提供的Jar包中有一些Bug,又懒得找其他部门重新打一个,所以就自己修改Jar包了。在修改Jar包的过程中遇到了几个问题,记...

1581
来自专栏deepcc

form表单无刷新提交文件(iframe)

40110
来自专栏挖掘大数据

Kafka定时清除过期数据

Kafka将数据持久化到了硬盘上,允许你配置一定的策略对数据清理,清理的策略有两个,删除和压缩。

1.1K6
来自专栏月牙寂

k8s源码分析-----kube-proxy(2)ProxyServer

第一时间获取文章,可以关注本人公众号 月牙寂道长 yueyajidaozhang

3764

扫码关注云+社区

领取腾讯云代金券