flask中的session介绍

在这里插入图片描述

flask中的session介绍

在Flask中,session是一个用于存储特定用户会话数据的字典对象。它在不同请求之间保存数据。它通过在客户端设置一个签名的cookie,将所有的会话数据存储在客户端。以下是如何在Flask应用中使用session的基本步骤:

首先,你需要设置一个秘钥,这是为了加密你的session数据:

from flask import Flask, session

app = Flask(__name__)

# Set the secret key to some random bytes. Keep this really secret!
app.secret_key = b'_5#y2L"F4Q8z\n\xec]/'

然后,你可以像操作字典一样操作session对象。以下是一个登录的例子:

from flask import Flask, session, redirect, url_for, escape, request

app = Flask(__name__)
app.secret_key = b'_5#y2L"F4Q8z\n\xec]/'


#from flask import escape
# 假设 session['username'] 是 "<script>alert('hacked!');</script>"
#safe_username = escape(session['username'])
# safe_username 现在是 "&lt;script&gt;alert('hacked!');&lt;/script&gt;"
# escape(session['username'])是在做HTML转义

@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():
    error = None
    if request.method == 'POST':
        username = request.form['username']
        password = request.form['password']
        if valid_login(username, password):
            session['username'] = request.form['username']
            return redirect(url_for('index'))
        else:
            error = 'Invalid username or password'
    return render_template('login.html', error=error)


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

Flask的session实现涉及到几个关键的组件:session对象、session_interface对象以及secure_cookie模块。以下是这些组件是如何工作以实现Flask的session的:

  1. Session对象:在Flask中,session被表示为一个名为session的字典对象。它是LocalProxy的实例,LocalProxy是一种可以动态引用当前运行环境(比如请求或应用上下文)的特定对象的代理类。当你尝试访问session对象的属性或方法时,LocalProxy会将这些操作转发到实际的会话对象,这个实际的会话对象由session_interface创建。
  2. SessionInterface对象SessionInterface是一个抽象基类,定义了用于处理session的接口。Flask自带的SecureCookieSessionInterface实现了这个接口,使用安全的签名cookie来存储session数据。当一个请求开始时,SecureCookieSessionInterface会从请求的cookies中提取出session数据,并创建一个新的SecureCookieSession对象。当请求结束时,如果SecureCookieSession对象被修改,SecureCookieSessionInterface会把它序列化并签名,然后存回到客户端的cookies中。【文末附源码解释】
  3. SecureCookie模块:这个模块实现了SecureCookieSession类,SecureCookieSession是一个用于存储实际session数据的字典子类,它的工作方式和普通的字典一样。

整体来看,Flask的session实现工作流程是这样的:

  • 当一个请求开始时,Flask会创建一个新的请求上下文,并通过SecureCookieSessionInterface从请求的cookies中提取出session数据,然后创建一个新的SecureCookieSession对象。
  • 当你在你的视图函数中操作session对象(比如设置session['username'] = 'John')时,实际上你是在操作这个SecureCookieSession对象。
  • 当请求结束时,Flask会检查SecureCookieSession对象是否被修改。如果被修改,Flask会通过SecureCookieSessionInterfaceSecureCookieSecureCookieSession对象序列化并签名,然后把它存回到响应的cookies中。
  • 当下一个请求来到时,这个过程会再次重复。

通常流程总结

  1. 当一个新用户(没有任何session数据的用户)首次访问你的Flask应用时,他们的请求中不会包含任何session数据。在这种情况下,Flask会为这个用户创建一个新的、空的session对象。这个新的session对象在初始状态下是空的,也就是说,它不包含任何数据。
  2. 如果在处理这个请求的过程中,你的代码修改了session对象(例如,通过设置session['username'] = 'John'),那么当请求结束时,Flask会把这个session对象序列化并签名,然后存入一个新的Cookie中。这个新的Cookie会被发送到客户端,一起与响应一起传送。
  3. 当这个用户下次访问你的Flask应用时,他们的请求将会携带这个包含了session数据的Cookie。Flask会在接收到这个请求时,从Cookie中提取出session数据,并创建一个新的session对象。这样,你的代码就可以继续访问和修改这个session对象了。

需要注意的是,如果一个请求没有修改session对象,那么Flask就不会在响应中设置新的Cookie。这是因为,没有必要把一个没有变化的session数据再次发送到客户端。

因此,即使一个新用户的首次请求中没有包含任何session数据,Flask也能正确地处理

SecureCookieSessionInterface

class SecureCookieSessionInterface(SessionInterface):
    """The default session interface that stores sessions in signed cookies
    through the :mod:`itsdangerous` module.
    """

    #: the salt that should be applied on top of the secret key for the
    #: signing of cookie based sessions.
    salt = "cookie-session"
    #: the hash function to use for the signature.  The default is sha1
    digest_method = staticmethod(hashlib.sha1)
    #: the name of the itsdangerous supported key derivation.  The default
    #: is hmac.
    key_derivation = "hmac"
    #: A python serializer for the payload.  The default is a compact
    #: JSON derived serializer with support for some extra Python types
    #: such as datetime objects or tuples.
    serializer = session_json_serializer
    session_class = SecureCookieSession

    def get_signing_serializer(self, app: Flask) -> URLSafeTimedSerializer | None:
        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,
        )

    def open_session(self, app: Flask, request: Request) -> SecureCookieSession | None:
        s = self.get_signing_serializer(app)
        if s is None:
            return None
        val = request.cookies.get(self.get_cookie_name(app))
        if not val:
            return self.session_class()
        # 获取session的最大有效期,单位为秒。
        max_age = int(app.permanent_session_lifetime.total_seconds())
        try:
            # 尝试使用序列化器s的loads方法,对session cookie的值val进行反序列化和签名验证。如果反序列化和验证成功,就用这些数据创建一个新的session对象,并返回
            data = s.loads(val, max_age=max_age)
            return self.session_class(data)
        except BadSignature:
            return self.session_class()

    def save_session(
        self, app: Flask, session: SessionMixin, response: Response
    ) -> None:
        name = self.get_cookie_name(app)
        domain = self.get_cookie_domain(app)
        path = self.get_cookie_path(app)
        secure = self.get_cookie_secure(app)
        samesite = self.get_cookie_samesite(app)
        httponly = self.get_cookie_httponly(app)

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

        # 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(
                    name,
                    domain=domain,
                    path=path,
                    secure=secure,
                    samesite=samesite,
                    httponly=httponly,
                )
                response.vary.add("Cookie")

            return

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

        expires = self.get_expiration_time(app, session)
        val = self.get_signing_serializer(app).dumps(dict(session))  # type: ignore
        response.set_cookie(
            name,
            val,  # type: ignore
            expires=expires,
            httponly=httponly,
            domain=domain,
            path=path,
            secure=secure,
            samesite=samesite,
        )
        response.vary.add("Cookie")

  1. SecureCookieSessionInterface类:这个类实现了session接口,使用安全的签名cookies来存储session数据。
  2. 类属性:
    • salt:加盐值,用于混淆session的加密过程,增加安全性。
    • digest_method:哈希函数,用于签名过程中对数据进行哈希处理,默认为sha1。
    • key_derivation:关键字派生,设置为"hmac",表示使用HMAC进行签名。
    • serializer:序列化器,用于将Python对象转换为可以在网络上传输的格式,这里使用的是JSON序列化器。
    • session_class:表示session的类,默认为SecureCookieSession。
  3. get_signing_serializer方法:用于获取一个签名序列化器,其作用是用来签名和反签名cookies的。如果应用没有设置秘钥app.secret_key,则返回None。
  4. open_session方法:在处理每个请求时调用,从请求的cookies中提取出session数据,反序列化并验证签名,得到session的数据。如果签名不合法,就会抛出BadSignature异常,然后返回一个空的session。
  5. save_session方法:在每个请求处理完后调用,将session数据序列化,签名,然后存入到响应的cookies中。如果session为空且已被修改,则删除cookie。只有当session被访问过或被修改,才会设置Vary: Cookie头。

在使用SecureCookieSessionInterface处理session时,Flask会保证session的安全性,即使session数据存储在客户端的cookies中,也无法被篡改,因为每个session cookie都被签名了。除非知道服务器的秘钥,否则无法伪造有效的session cookie。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/48122.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Linux内核中的链表、红黑树和KFIFO

lLinux内核代码中广泛使用了链表、红黑树和KFIFO。 一、 链表 linux内核代码大量使用了链表这种数据结构。链表是在解决数组不能动态扩展这个缺陷而产生的一种数据结构。链表所包含的元素可以动态创建并插入和删除。链表的每个元素都是离散存放的&#xff0c;因此不需要占用连…

kafka消息监听

1&#xff0c;spring配置kafka网址 2&#xff0c;listener Component public class OrderMsgListener {KafkaListener(topics "order",groupId "order-service")public void listen(ConsumerRecord record){System.out.println("收到消息&#xf…

IPv6 over IPv4

IPv6 over IPv4隧道简介 IPv6 over IPv4隧道可实现IPv6网络孤岛之间通过IPv4网络互连。由于IPv4地址的枯竭和IPv6的先进性&#xff0c;IPv4过渡为IPv6势在必行。因为IPv6与IPv4的不兼容性&#xff0c;所以需要对原有的IPv4设备进行替换。但是如果贸然将IPv4设备大量替换所需成…

11.python设计模式【责任链模式】

内容&#xff1a;使多个对象都有机会处理请求&#xff0c;从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链&#xff0c;并沿着这条链传递该请求&#xff0c;直到有一个对象处理它为止。角色&#xff1a; 抽象处理者&#xff08;Handler&#xff09;具体处理…

【用户体验分析报告】 按需加载组件,导致组件渲染卡顿,影响交互体验?组件拆包预加载方案来了!

首先&#xff0c;我们看一些针对《如何提升应用首屏加载体验》的文章&#xff0c;提到的必不可少的措施&#xff0c;便是减少首屏幕加载资源的大小&#xff0c;而减少资源大小必然会想到按需加载措施。本文提到的便是一个基于webpack 插件与 react 组件实现的一套研发高度自定义…

索马里ECTN认证开船后办?都可以办的,

索马里ECTN认证开船后办&#xff1f;都可以办的&#xff0c;没有特别时间要求&#xff0c;可以在开船前办&#xff0c;也可以在开船后再办。因为索马里ECTN货物跟踪单看上去像是一份“证书”的文件&#xff0c;主要作用是用于目的港清关&#xff0c;所以很多客户习惯把它称为EC…

50条必背JAVA知识点(三)

31.面向对象中两个重要的概念&#xff1a;类&#xff1a;对一类事物的描述&#xff0c;是抽象的、概念上的定义对象&#xff1a;是实际存在的该类事物的每个个体&#xff0c;因而也称为实例(instance) 32.虚拟机栈&#xff0c;即为平时提到的栈结构。局部变量存储在栈结构中&am…

【数据动态填充到element表格;将带有标签的数据展示为文本格式】

一&#xff1a;数据动态填充到element表格&#xff1b; 二&#xff1a;将带有标签的数据展示为文本格式&#xff1b; 1、 <el-row><el-col :span"24"><el-tabs type"border-card"><el-tab-pane label"返回值"><el-…

IL汇编字符串连接

在此实现了一个基本的IL汇编程序&#xff1b; 了解MSIL汇编和IL汇编评估堆栈_bcbobo21cn的博客-CSDN博客 它用了下面两句来在屏幕输出字符串&#xff0c; ldstr "I am from the IL Assembly Language..." call void [mscorlib]System.Console::WriteLine (string) …

WMS是什么意思,WMS有什么功能

阅读本篇文章&#xff0c;您可以了解到&#xff1a;1、WMS的定义&#xff1b;2、WMS的功能&#xff1b;3、WMS的好处&#xff1b;4、WMS的未来。 一、WMS的定义 WMS全称为Warehouse Management System&#xff0c;即仓库管理系统&#xff0c;是一种用于管理和控制仓库操作的软…

day42-Live User Filter(实时用户过滤器)

50 天学习 50 个项目 - HTMLCSS and JavaScript day42-Live User Filter&#xff08;实时用户过滤器&#xff09; 效果 index.html <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport…

CTF PWN-攻防世界CGfsb格式化字符串漏洞

文章目录 前言格式化字符串漏洞格式化字符串漏洞基本原理简单典型案例 漏洞的危害与利用拒绝服务攻击内存数据读取内存数据覆盖 攻防世界&#xff1a;CGfsg题目思路简析任意地址覆写 总结 前言 距离 2021 年年底短暂接触学习 CTF PWN 相关知识&#xff08;CTF PWN-攻防世界XCT…

光伏储能行业MES系统解决方案

万界星空科技光伏储能行业mes解决方案连接起仓储物流、生产计划、制程管理、品质管理等各个模块&#xff0c;覆盖全厂的各个工序段&#xff0c;提供计划的执行、跟踪以及所有资源(人、设备、物料等)的当前状态&#xff0c;帮助企业实现产品质量、生产效率的提升。 万界星空平台…

灵雀云Alauda MLOps 现已支持 Meta LLaMA 2 全系列模型

在人工智能和机器学习领域&#xff0c;语言模型的发展一直是企业关注的焦点。然而&#xff0c;由于硬件成本和资源需求的挑战&#xff0c;许多企业在应用大模型时仍然面临着一定的困难。为了帮助企业更好地应对上述挑战&#xff0c;灵雀云于近日宣布&#xff0c;企业可通过Alau…

大数据实时链路备战 —— 数据双流高保真压测 | 京东云技术团队

一、大数据双流建设 1.1 数据双流 大数据时代&#xff0c;越来越多的业务依赖实时数据用于决策&#xff0c;比如促销调整&#xff0c;点击率预估、广告分佣等。为了保障业务的顺利开展&#xff0c;也为了保证整体大数据链路的高可用性&#xff0c;越来越多的0级系统建设双流&…

Leetcode-每日一题【剑指 Offer 66. 构建乘积数组】

题目 给定一个数组 A[0,1,…,n-1]&#xff0c;请构建一个数组 B[0,1,…,n-1]&#xff0c;其中 B[i] 的值是数组 A 中除了下标 i 以外的元素的积, 即 B[i]A[0]A[1]…A[i-1]A[i1]…A[n-1]。不能使用除法。 示例: 输入: [1,2,3,4,5]输出: [120,60,40,30,24] 提示&#xff1a; 所…

UVM重点归纳(快收藏 !)

factory机制 利用工厂机制的一般实现步骤&#xff1a; 1.继承 范式&#xff1a; class comp_type/obj_type extends uvm_component/uvm_object; 实例&#xff1a; class comp1/obj1 extends uvm_component/uvm_object; 2.注册 范式&#xff1a; uvm_component/object_utils…

组件开发系列--Apache Commons Chain

一、前言 Commons-chain是apache commons中的一个子项目,主要被使用在"责任链"的场景中,struts中action的调用过程,就是使用了"chain"框架做支撑.如果你的项目中,也有基于此种场景的需求,可以考虑使用它. 在责任链模式里&#xff0c;很多对象由每一个对象对…

Python中运行取消Python console模式

在Python里run的时候突然会发现&#xff0c;进入的不是run模式&#xff0c;而是console模式&#xff0c;这种运行模式能保留你每次的运行历史&#xff0c;因为会重开一个运行小页面&#xff0c;关闭操作如下&#xff1a;

opencv-18 什么是色彩空间?

1.什么是色彩空间类型&#xff1f; 色彩空间类型&#xff0c;也称为颜色空间类型或色彩模型&#xff0c;是一种表示图像中颜色的方式。在计算机图形学和数字图像处理中&#xff0c;有许多种色彩空间类型&#xff0c;每种类型有不同的表达方式和特点。 常见的色彩空间类型包括&a…