http的会话控制(flask)

http的会话控制

所谓的会话(session),就是客户端浏览器和服务端网站之间一次完整的交互过程.

会话的开始是在用户通过浏览器第一次访问服务端网站开始.

会话的结束时在用户通过关闭浏览器以后,与服务端断开.

所谓的会话控制,就是在客户端浏览器和服务端网站之间,进行多次http请求响应之间,记录、跟踪和识别用户的信息而已。

为什么要有会话控制?因为 http 是一种无状态协议,浏览器请求服务器是无状态的。

无状态:指一次用户请求时,浏览器、服务器无法知道之前这个用户做过什么,对于服务端而言,客户端的每次请求都是一次新的请求。

无状态原因:浏览器与服务器是使用 socket 套接字进行通信的,服务器将请求结果返回给浏览器之后,会关闭当前的 socket 连接,而且客户端也会在处理页面完毕之后销毁页面对象。

有时需要保持下来用户浏览的状态,比如用户是否登录过,浏览过哪些商品等

实现状态保持主要有两种方式:

  • 在客户端存储信息使用Cookie(废弃),token[jwt,oauth]

  • 在服务器端存储信息使用Session,数据库

Cookie是由服务器端生成一段能识别用户身份的文本信息,发送给客户端浏览器,浏览器会将Cookie的key/value保存,下次请求同一网站时就随着请求头自动发送该Cookie给服务器(前提是浏览器设置为启用cookie)。Cookie的key/value可以由服务器端自己定义。

使用场景: 登录状态, 浏览历史(网站足迹), 购物车[不登录也可以使用购物车]

Cookie是存储在浏览器中的一段纯文本信息,建议不要存储敏感信息如密码,因为电脑上的浏览器可能被其它人使用

Cookie基于域名安全,不同域名的Cookie是不能互相访问的。

如访问fuguang.com时向浏览器中写了Cookie信息,使用同一浏览器访问baidu.com时,无法访问到fuguang.com写的Cookie信息,只能获取到baidu.com的Cookie信息。

浏览器的同源策略针对cookie也有限制作用。

当浏览器请求某网站时,浏览器会自动将本网站下所有Cookie信息随着http请求头提交给服务器,所以在request中可以读取Cookie信息

设置cookie

设置cookie需要通过flask的Response响应对象来进行设置,由响应对象会提供了方法set_cookie给我们可以快速设置cookie信息。

from flask import Flask, make_response, request, redirect

app = Flask(__name__)

@app.route("/set_cookie")
def set_cookie():
    """cookie的设置"""
    # cookie保存客户端浏览器中的,所以cookie必须跟着响应对象返回给客户端
    response = make_response("set_cookie")
    # 基于响应对象提供的set_cookie方法,可以设置单个cookie
    # response.set_cookie("变量名", "变量值", max_age="变量有效期")
    response.set_cookie("user_id", "100") # 如果没有设置max_age,则当前cookie变量会在浏览器关闭(会话结束以后被浏览器删除)
    response.set_cookie("username", "xiaoming", max_age=3600)  # 如果设置max_age,则按秒作为时间单位,设置cookie的有效时间
    response.set_cookie("number", "10000", max_age=30)         # 如果设置max_age,则按秒作为时间单位,设置cookie的有效时间
    return response

@app.route("/get_cookie")
def get_cookie():
    """cookie的读取"""
    print("user_id=", request.cookies.get("user_id") )
    print("username=", request.cookies.get("username"))
    print("number=", request.cookies.get("number"))
    return "get_cookie"

# 删除cookie
@app.route("/del_cookie")
def del_cookie():
    """cookie的删除"""
    # cookie保存客户端浏览器中的,所以服务端无法直接删除cookie
    # 要实现删除cookie,只能告诉浏览器,cookie过期了,让浏览器自动删除
    response = make_response("del_cookie")
    response.set_cookie("user_id", "", max_age=0)
    response.set_cookie("username", "", max_age=0)
    return response

# 基于cookie实现用户的例子
@app.route("/login", methods=["get", "post"])
def login():
    """基于cookie实现登录"""
    form = """
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>Title</title>
    </head>
    <body>
      <form action="" method="post">
        账号:<input type="text" name="username"><br><br>
        密码:<input type="password" name="password"><br><br>
        <input type="submit" value="登录">
      </form>
    </body>
    </html>
    """
    if request.method == "GET":
        return make_response(form)

    """接收客户端POST提交表单数据"""
    # 暂时不使用数据库,我们模拟用户身份判断代码
    username = request.form.get("username")
    password = request.form.get("password")
    if username == "root" and password == "123456":
        """认证通过"""
        # 基于cookie保存登录状态
        response = make_response("登录成功!")
        response.set_cookie("username", username, max_age=7200)
        response.set_cookie("user_id", username, max_age=7200)
        return response
    else:
        """认证失败"""
        # 返回GET请求的login登录页面
        response = redirect("/login")
        return response


@app.route("/user")
def user():
    """在部分需要认证身份的页面中,基于cookie判断用户登录状态"""
    if not request.cookies.get("username"):
        response = redirect("/login")
        return response

    return "个人中心的信息展示"

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


设置和删除cookie

模拟登录

Session

对于敏感、重要的信息,建议要存储在服务器端,不能存储在浏览器中,如手机号、验证码等信息

在服务器端进行状态保持的方案就是Session

Session依赖于Cookie,session的ID一般默认通过cookie来保存到客户端。名字一般叫:sessionid

flask中的session需要加密,所以使用session之前必须配置SECRET_KEY选项,否则报错。

注意:一般web框架都是把session数据保存到服务端,但是flask里面的session是基于token方式存储在客户端的,并没有安装传统的方式保存在服务端的文件中。

session的ID存在有效期的,默认是会话期,会话结束了,session_id就废弃了。

设置session
from flask import Flask, session,redirect,request,make_response


app = Flask(__name__)

# 因为flask中的session是基于cookie加密实现的,所以使用之前必须设置SECRET_KEY选项
app.config["SECRET_KEY"] = "dskafmdfmem2w4m234mfmvdfmasdkqaso3423"


@app.route("/set_session")
def set_session():
    """设置session"""
    session["username"] = "xiaoming"
    session["user_id"] = 31
    session["data"] = [1, 2, 3, 5, "AAAA"]

    return "set_session"

@app.route("/get_session")
def get_session():
    """读取session"""
    print(f'username={session.get("username")}')
    print(f'user_id={session.get("user_id")}')
    print(f'data={session.get("data")}')
    return "get_session"

@app.route("/del_session")
def del_session():
    """删除session"""
    session.pop("username")
    session.pop("data")
    return "del_session"

# 基于session实现用户登录认证
@app.route("/login", methods=["get", "post"])
def login():
    """基于session实现登录认证"""
    form = """
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>Title</title>
    </head>
    <body>
      <form action="" method="post">
        账号:<input type="text" name="username"><br><br>
        密码:<input type="password" name="password"><br><br>
        <input type="submit" value="登录">
      </form>
    </body>
    </html>
    """
    if request.method == "GET":
        return make_response(form)

    """接收客户端POST提交表单数据"""
    # 暂时不使用数据库,我们模拟用户身份判断代码
    username = request.form.get("username")
    password = request.form.get("password")
    if username == "root" and password == "123456":
        """认证通过"""
        # 基于session保存登录状态
        session["username"] = "root"
        session["user_id"]  = "root"
        response = make_response("登录成功!")
        return response
    else:
        """认证失败"""
        # 返回GET请求的login登录页面
        response = redirect("/login")
        return response


@app.route("/user")
def user():
    """在部分需要认证身份的页面中,基于session判断用户登录状态"""
    if not session.get("username"):
        response = redirect("/login")
        return response

    return "个人中心的信息展示"

if __name__ == "__main__":
    app.run(host='127.0.0.1',port=5000,debug=True)

设置session

可以通过客户端浏览器中的cookie观察到,在默认情况下,flask中的session数据会被保存到cookie中的(不安全)。当然,将来我们可以采用flask-session第三方模块把数据转存到服务端其他的存储设备,例如:redis或者mysql中。

删除session

模拟登录:

<think>好的,我现在需要准备关于Flask框架中会话管理的教学内容。首先,我得回忆一下Flask会话管理机制,确保自己理解正确。Flask会话是基于客户端的cookie,使用密钥签名来保证安全性,这点很重要,必须强调密钥配置的重要性,避免安全漏洞。 接下来,我需要整理会话的基本用法,比如如何导入session对象,设置和获取会话数据。比如session['username'] = 'user1',然后session.get('username')。还要提到会话的持久性,默认情况下,会话在浏览器关闭后失效,但可以通过设置permanent_session_lifetime来调整。 然后,需要考虑安全方面的问题。比如必须设置SECRET_KEY,否则会话数据容易被篡改。同时,提醒用户不要存储敏感信息在客户端会话中,因为数据虽然签名但并未加密。可能还需要提到Flask-Session扩展,它支持服务器端存储会话,比如使用Redis或数据库,适合更高级的需求。 另外,常见问题解答部分可能会有学生问会话和cookie的区别,需要解释清楚Flask会话是基于签名的cookie,而普通cookie是不安全的。还要处理如何清除会话数据,使用session.clear()或者session.pop('key')。 可能需要演示一个简单的例子,比如用户登录后存储用户名,登出时清除。代码示例要准确,确保语法正确,比如使用@app.route装饰器,正确导入session对象。 还要注意版本兼容性,不同Flask版本是否有差异,但目前主流版本应该变化不大。最后,总结关键点,强调安全和正确使用会话的方法,确保学生理解最佳实践。 检查是否有遗漏的部分,比如配置项的具体写法,比如app.config['PERMANENT_SESSION_LIFETIME'] = timedelta(days=7),是否需要导入timedelta。确保示例代码正确,避免拼写错误,比如session的拼写是否正确,是否漏掉了必要的导入语句。 可能还需要比较Flask会话和其他框架(比如Django)的会话机制,但根据用户要求,可能不需要深入,除非用户问到。保持教学内容简洁,重点突出,结构清晰,分步骤讲解,从基本概念到实际应用,再到安全注意事项,帮助学生逐步掌握。</think>以下是Flask框架会话管理的系统化教学指南: --- ### 一、会话管理核心机制 1. **客户端存储**:会话数据默认以**签名cookie**形式存储在客户端 2. **安全签名**:通过`SECRET_KEY`进行HMAC签名,防止数据篡改 3. 序列化格式:采用JSON格式序列化数据(Flask 2.3+默认) 安全警示: $ \text{未设置SECRET_KEY} \Rightarrow \text{会话可被篡改} $ --- ### 二、基础配置流程 ```python from flask import Flask, session from datetime import timedelta app = Flask(__name__) app.secret_key = 'your_secure_key_here' # 应使用随机生成的安全密钥 app.config['PERMANENT_SESSION_LIFETIME'] = timedelta(days=7) # 持久会话有效期 ``` --- ### 三、核心操作方法 1. **数据存取** ```python # 设置会话值 session['username'] = 'admin' session['logged_in'] = True # 获取数据(推荐安全写法) username = session.get('username', 'guest') # 删除数据 session.pop('username', None) ``` 2. **会话持久化控制** ```python session.permanent = True # 启用持久会话 ``` 3. **会话清空** ```python session.clear() # 删除所有会话数据 ``` --- ### 四、安全增强实践 1. **密钥安全** ```python import secrets print(secrets.token_hex(32)) # 生成32字节安全密钥 ``` 2. **服务器端存储方案(使用Flask-Session扩展)** ```python from flask_session import Session app.config['SESSION_TYPE'] = 'redis' # 支持redis/memcached/filesystem等 Session(app) ``` 3. **敏感数据防护原则** - 始终避免存储敏感信息(如密码、API密钥) - 签名 ≠ 加密,重要数据应结合数据库存储 --- ### 五、典型应用场景示例 **用户认证流程实现** ```python @app.route('/login', methods=['POST']) def login(): # 验证逻辑通过后 session['user_id'] = user.id session['logged_in'] = True session.permanent = True # 持久会话 return redirect(url_for('dashboard')) @app.route('/logout') def logout(): session.clear() return redirect(url_for('home')) ``` --- ### 六、调试与问题排查 1. **查看Cookie内容**: - 使用浏览器开发者工具检查`session`cookie - 通过Flask的调试器检查`session`对象 2. **常见错误处理**: ```python # 确保响应提交前修改会话 session.modified = True # 强制保存变更 ``` --- ### 七、性能优化建议 1. **会话精简原则**:保持会话数据最小化(建议<4KB) 2. **存储策略选择**: - 小数据量:默认客户端存储 - 大数据/敏感数据:采用服务器端存储 3. **有效期控制**:根据业务需求精确设置`PERMANENT_SESSION_LIFETIME` --- ### 八、安全审计清单 1. [ ] SECRET_KEY已设置为强随机值 2. [ ] 未在会话中存储敏感信息 3. [ ] 已正确配置HTTPS传输 4. [ ] 会话超时时间设置合理 5. [ ] 实施了CSRF保护机制 数学表达示例: 会话签名验证流程可表示为: $ \text{Valid} = \text{VerifyHMAC}(\text{session\_data}, \text{secret\_key}) $ 通过本指南,您可以系统掌握Flask会话管理的关键技术和安全实践。建议结合具体业务场景选择合适的会话存储策略,并定期进行安全审计。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值