我在domain.com上运行了一个烧瓶
我还在另一台运行在username.domain.com上的服务器上有另一个烧瓶实例
通常用户通过domain.com登录
但是,对于付费用户,他们可以登录username.domain.com
使用flask,我如何确保在domain.com和username.domain.com之间共享会话,同时确保他们只能访问特定匹配的username.domain.com?
我担心这里的安全。
答案 0 :(得分:4)
修改: 之后,在阅读完整的问题后,我发现原来的答案不是您正在寻找的。 strong>
我已将此答案底部的原件留给了Google员工,但修改后的版本如下。
Cookie会自动发送到域上的子域(在大多数现代浏览器中,域名必须包含一个句点(表示TLD)才能发生此行为)。身份验证需要作为预处理器进行,并且您的会话需要从集中式源进行管理。让我们来看看吧。
要确认,我将继续(假设您已经告诉我)您的设置如下:
首先必须克服的问题是将会话存储在两个服务器都可访问的位置。由于默认情况下会话存储在磁盘上(并且两台服务器显然不共享相同的硬盘驱动器),因此我们需要对现有设置和用户配置文件的新Flask应用程序进行一些修改。 / p>
第一步是选择存储会话的位置,由DBMS(如MySQL,Postgres等)提供支持的数据库是一种常见的选择,但人们也常常选择将它们放在更短暂的地方,如Memcachd或Redis for示例
在这两个截然不同的系统之间进行选择的简短版本分解为以下内容:
<强>数据库强>
记忆(Redis / Memchachd / etc。)
虽然根据每个用户的经验水平设置Redis会更加困难,但这是我推荐的选项。您可以看到执行此操作的示例here。
我认为其余部分在原始答案中有所涉及,其中一部分演示了用户名与数据库记录的匹配(较大的代码块)。
单个Flask应用的旧解决方案
首先,您必须设置Flask来处理子域,这就像在配置文件中指定新的变量名一样简单。例如,如果您的域名是cakeninja.net,则会将以下内容附加到Flask配置中。
SERVER_NAME = "cakeninja.net"
您可以阅读有关此选项here的更多信息。
这里需要注意的是,如果您只是在本地主机上工作,那将是非常困难的(如果不是不可能的话)。如上所述,浏览器通常不会在名称(TLD)中没有点的情况下将cookie发送到域的子域。在许多操作系统中,默认情况下,Localhost也不会设置为允许子域。有一些方法可以这样做,比如定义您可以查看的自己的DNS条目(* /etc/hosts
在* UNIX上,%system32%/etc/hosts
在Windows上。)
准备好配置后,您需要为子域野心定义Blueprint
。
这很容易做到:
from flask import Blueprint
from flask.ext.login import current_user
# Create our Blueprint
deep_blue = Blueprint("subdomain_routes", __name__, subdomain="<username>")
# Define our route
@deep_blue.route('/')
def user_index(username):
if not current_user.is_authenticated():
# The user needs to log in
return "Please log in"
elif username != current_user.username:
# This is not the correct user.
return "Unauthorized"
# It's the right user!
return "Welcome back!"
这里的技巧是确保用户对象的__repr__
包含用户名密钥。例如......
class User(db.Model):
username = db.Column(db.String)
def __repr__(self):
return "<User {self.id}, username={self.username}>".format(self=self)
要注意的是,当用户名包含不在URL中工作的特殊字符(空格,@,?等)时会出现问题。为此,您需要对用户名强制执行限制,或者首先正确地转义名称,并在验证时将其取消。
如果您有任何问题或要求,请询问。这是在我喝咖啡休息期间这样做的,所以有点匆忙。
答案 1 :(得分:1)
您可以使用内置的Flask会话(基于cookie的客户端会话)来执行此操作。要允许用户登录“ .domain.com”中的多个子域,只需指定
app.config['SESSION_COOKIE_DOMAIN'] = '.domain.com'
,并且客户端的浏览器将具有一个会话cookie,该会话cookie允许他登录到“ domain.com”上的每个Flask实例。 仅当Flask的每个实例都具有相同的app.secret_key
时,此方法才有效