gpt4 book ai didi

python - 如何限制来自任何浏览器的一个 session 以获取 flask 中的用户名?

转载 作者:太空狗 更新时间:2023-10-29 21:31:15 25 4
gpt4 key购买 nike

我正在使用一个 gunicorn 服务器,我试图找出一种方法来限制每个用户名只有一个 session ,即如果用户 A 从 Chrome 登录到应用程序,他不应该能够通过 Firefox 登录,除非他登录在 chrome 之外,或者不应该能够在 chrome 本身中打开另一个 TAB。

如何为浏览器生成一个唯一的 ID 并将其存储在数据库中,以便在用户注销或 session 过期之前,用户无法通过任何其他浏览器登录。

最佳答案

将 session 限制到单个选项卡的一种可能方法涉及在页面加载时创建一个随机 token 并将该 token 嵌入到页面中。这个最近生成的 token 也存储在用户的 session 中。这将类似于各种框架添加验证 token 以防止 CSFR 的方式。攻击。

简要示例:

  • 用户在 Firefox 的选项卡 1 中加载页面。 Token1生成,嵌入并存储在session中
  • 用户在 Firefox 的选项卡 2 中加载页面。 Token2 生成、嵌入并存储在 session 中。这会覆盖之前的值。
  • 用户在 Chrome 的标签页 1 中加载页面。 Token3 生成、嵌入并存储在 session 中。这会覆盖以前的值。

此时,用户在 3 个选项卡中打开了页面。但是,用户的 session 只存储了 Token3。此方法可防止用户被锁定(不同的 IP 地址、不同的用户代理字符串、隐身模式等),因为每个新 session 只会生成一个新 token 。最新的加载成为事件窗口,立即使所有以前的 session 失效。

接下来,每当页面与服务器交互(点击链接、提交数据等)时,页面中嵌入的 token 也会被发送。服务器验证传递的 token 是否与 session 中的 token 匹配。如果它们匹配,则操作成功。如果它们不匹配,则服务器返回失败消息。


您可以通过多种方式生成随机数,但您可能需要一些安全的方法。我们将使用 example来自另一个问题:

import string
import random
...
N = 20 # Length of the string we want, adjust as appropriate
''.join(random.SystemRandom().choice(string.ascii_uppercase + string.digits) for _ in range(N))

这使用 random.SystemRandom ,这比简单地使用 random.choice 更安全


在页面加载时,您需要检查现有 token 是否有效,生成随机 token 并将其存储在用户 session 中。因为我们到处都想要这个,所以让我们先做一个装饰器,以减少以后的重复代码。装饰器检查 session 是否有效,如果无效,您可以选择要做什么(插入您自己的逻辑)。它还设置一个 session token 。这是必需的(或者您需要排除主页的逻辑),否则您将进入无限循环,用户尝试加载主页时,没有 token ,失败并重复该过程。我通过 else 子句在每个页面加载时重新生成 token 。如果你没有实现 if 部分,这个装饰器就毫无意义,因为两条路径执行相同的操作并且只是在页面加载时重置 token 。 if 中的逻辑将阻止用户进行多个 session 。

from flask import session
from functools import wraps

def random_string(length):
return ''.join(random.SystemRandom().choice(string.ascii_uppercase + string.digits) for _ in range(length))

def validate_token(f):
@wraps(f)
def wrapper(existing_token, *args, **kwargs):
if session['token'] != existing_token:
# Logic on failure. Do you present a 404, do you bounce them back to your main page, do you do something else?
# It is IMPORTANT that you determine and implement this logic
# otherwise the decorator simply changes the token (and behaves the same way as the else block).
session['token'] = random_string(20)
else:
session['token'] = random_string(20)
return f(*args, **kwargs)
return wrapper

现在在我们的路由中,我们可以将这个装饰器应用于每个路由,以便在每次页面加载时更新用户 session :

from flask import render_template

@app.route('/path')
@validate_token
def path(token=None):
return render_template('path.html', token=session['token'])

在您的模板中,您想在任何需要阻止 session 继续的地方使用此 token 值。例如,将其放在链接上、表单中(尽管 Flask has a method of CSRF protection 已经存在)等。服务器本身可以检查传递的 token 是否有效。该模板可能看起来像这样简单:

<a href="{{ url_for('path', token=token) }}">Click here to continue</a> 

关于python - 如何限制来自任何浏览器的一个 session 以获取 flask 中的用户名?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31281470/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com