常量Flask会话ID

8 投票
3 回答
5478 浏览
提问于 2025-04-17 15:43

我有一个 Flask 应用程序,是通过 Nginx+WSGI(FastCGI 和 Gevent)来提供服务的,并且使用标准的 Flask 会话。我并没有使用 session.permanent=True 或其他额外的选项,只是简单地在默认配置中设置了 SECRET_KEY

我并没有在会话中保存任何(键,值)对,只是依靠 SID = session['_id'] 这个条目来识别返回的用户。我使用以下代码来读取 SID

@page.route ('/')
def main (page='home', template='index.html'):

    if not request.args.get ('silent', False):
        print >> sys.stderr, "Session ID: %r" % session['_id']

我做了以下观察:

  1. 对于相同的 IP 地址,但不同的浏览器,我得到不同的 SIDs - 这是可以预期的;
  2. 对于不同的 IP 和相同的浏览器,我再次得到不同的 SIDs - 也是可以预期的;
  3. 对于相同的 IP 地址和相同的浏览器,我得到相同的 SID - 这也是可以预期的;

现在,第三点很有趣,因为即使我 删除 了相应的 cookie,SID 仍然保持不变!在某种程度上,这也可以理解,但实际上我本来期待不同的 cookie 之间 SID 会有所变化。但我看到的唯一区别是

session.new is True

在删除 cookie 后的 第一次 请求中。即使这样也是非常可以预期的;但考虑到这些事实,我面临以下问题:

  1. 这是否意味着对于坐在 同一个 IP 后面的 不同 用户(使用相同的浏览器配置),我的后端会把他们误认为是 同一个 用户?

  2. 如果第一点不是这样,那么这些“粘性”会话的当前行为实际上是相当不错的,因为这避免了我的用户因为删除相应的 cookie 而丢失数据的情况。

    他们仍然可以通过使用相同的浏览器从同一网络重新访问网站来挽救局面。我喜欢这样,但只有在第一点不是这样的时候。

  3. 我假设第一点实际上会让我遇到麻烦,结论是否应该是在会话中保存一个 token,因此接受用户可以通过简单地删除他的 cookie 来“自毁”的命运?

  4. 或者有没有办法告诉 Flask 为每个新 cookie 提供不同的 SIDs

实际上,这个问题是因为我使用了一个负载测试服务,它模拟了 不同 用户(在同一个 IP 上),但我的后端一直把他们视为同一个用户,因为相应的 SIDs 都是相同的。

这个应用程序可以在 http://webed.blackhan.ch 上进行测试(发布后将移至 https://notex.ch [一个基于浏览器的文本编辑器])。感谢你的回答。

3 个回答

0

现在是2022年,Flask-Session确实支持通过session.sid来获取一个生成的UUID,这个UUID看起来像这样:

print(session.sid)
>>> f9c792fa-70e0-46e3-b84a-3a11813468ce

来自官方文档https://flasksession.readthedocs.io/en/latest/

sid

会话ID,我们内部使用uuid.uuid4()来生成一个会话ID。你可以通过session.sid来访问它。

0

session['_id'] 其实并不是一个真正的会话标识符。它只是 Flask-Login 用来实现 会话保护 的一个值。

标准的 Flask 会话并没有 SID(会话标识符)——因为这样做没有意义,因为会话的实际内容是存储在 cookie 里的。你也可以看看 这个链接

7

看起来你在使用Flask-Login这个扩展。这里是生成id令牌的代码:

def _create_identifier():
    base = unicode("%s|%s" % (request.remote_addr,
                              request.headers.get("User-Agent")), 'utf8', errors='replace')
    hsh = md5()
    hsh.update(base.encode("utf8"))
    return hsh.digest()

其实就是 md5(ip_address + user_agent) 的结果。

Flask使用Werkzeug的安全cookie来存储这个标识符。安全cookie顾名思义就是比较安全的:

这个模块实现了一种客户端无法修改的cookie,因为它添加了一个服务器会检查的校验和。如果你只有用户id或者其他标记已登录用户的东西,可以用它来替代会话。

撰写回答