记住我
“记住我”的功能很难实现。但是,Flask-Login 几乎透明地实现它 - 只要把 remember=True
传递给 login_user
。一个 cookie 将会存储在用户计算机中,如果用户会话中没有用户 ID 的话,Flask-Login 会自动地从 cookie 中恢复用户 ID。cookie 是防纂改的,因此如果用户纂改过它(比如,使用其它的一些东西来代替用户的 ID),它就会被拒绝,就像不存在。
该层功能是被自动实现的。但你能(且应该,如果你的应用处理任何敏感的数据)提供 额外基础工作来增强你记住的 cookie 的安全性。
可选令牌
使用用户 ID 作为记住的令牌值不一定是安全的。更安全的方法是使用用户名和密码联合的 hash 值,或类似的东西。要添加一个额外的令牌,向你的用户对象添加一个方法:
get_auth_token()
返回用户的认证令牌(返回为 unicode
)。这个认证令牌应能唯一识别用户,且不易通过用户的公开信息,如 UID 和名称来猜测出——同样也不应暴露这些信息。
相应地,你应该在 LoginManager
上设置一个 token_loader
函数, 它接受令牌(存储在 cookie 中)作为参数并返回合适的 User 对象。
make_secure_token
函数用于便利创建认证令牌。它会连接所有的参数,然后用应用的密钥来 HMAC 它确保最大的密码学安全。(如果你永久地在数据库中存储用户令牌,那么你会希望向令牌中添加随机数据来阻碍猜测。)
如果你的应用使用密码来验证用户,在认证令牌中包含密码(或你应使用的加盐值的密码 hash )能确保若用户更改密码,他们的旧认证令牌会失效。
”新鲜的“登录(Fresh Logins)
当用户登入,他们的会话被标记成“新鲜的”,就是说在这个会话只中用户实际上登录过。当会话销毁用户使用“记住我”的 cookie 重新登入,会话被标记成“非新鲜的”。login_required
并不在意它们之间的不同,这适用于大部分页面。然而,更改某人 的个人信息这样的敏感操作应需要一个“新鲜的”的登入。(像修改密码这样的操作总是需要 密码,无论是否重登入。)
fresh_login_required
,除了验证用户登录,也将确保他们的登录是“新鲜的”。如果不是“新鲜的”,它会把用户送到可以重输入验证条件的页面。你可以定制 fresh_login_required
就像定制 login_required
那样,通过设置 LoginManager.refresh_view
,needs_refresh_message
,和 needs_refresh_message_category
:
login_manager.refresh_view = "accounts.reauthenticate"
login_manager.needs_refresh_message = (
u"To protect your account, please reauthenticate to access this page."
)
login_manager.needs_refresh_message_category = "info"
或者提供自己的回调来处理“非新鲜的”刷新:
@login_manager.needs_refresh_handler
def refresh():
# do stuff
return a_response
调用 confirm_login
函数可以重新标记会话为”新鲜“。
Cookie 设置
cookie 的细节可以在应用设置中定义。
REMEMBER_COOKIE_NAME | 存储“记住我”信息的 cookie 名。 默认值: remember_token |
REMEMBER_COOKIE_DURATION | cookie 过期时间,为一个 datetime.timedelta 对象。 默认值: 365 天 (1 非闰阳历年) |
REMEMBER_COOKIE_DOMAIN | 如果“记住我” cookie 应跨域,在此处设置域名值 (即 .example.com 会允许 example 下所有子域 名)。 默认值: None |
REMEMBER_COOKIE_PATH | 限制”记住我“ cookie 存储到某一路径下。 默认值: / |
REMEMBER_COOKIE_SECURE | 限制 “Remember Me” cookie 在某些安全通道下有用 (典型地 HTTPS)。默认值: None |
REMEMBER_COOKIE_HTTPONLY | 保护 “Remember Me” cookie 不能通过客户端脚本访问。 默认值: False |