Flask-Login 为 Flask 提供了会话管理。它处理日常的登入、登出并长期保留用户会话。
它会:
无论如何,它不会:
对一个使用 Flask-Login 的应用,最重要的部分就是 LoginManager 类。你应该在代 码中的某处为你的应用创建一个它的实例,像这样:
login_manager = LoginManager()
登录管理器包含了让你的应用与 Flask-Login 协同工作的代码,诸如如何从 ID 加载一个 用户、当用户需要登录时跳转到哪里等等。
一旦创建了实际的应用对象,你可以这样配置它来实现登录功能:
login_manager.setup_app(app)
你需要提供一个 user_loader 回调。这个回调用于从会话中存储的用户 ID 重新加载用户对象。它应该接受一个用户的 unicode ID,并返回相应的用户对象。 例如:
@login_manager.user_loader
def load_user(userid):
return User.get(userid)
如果 ID 无效,它应该返回 None ( 而不是抛出异常 )。(在这种情况下,ID 会 被手动从会话中移除且处理会继续。)
用户通过验证后,用 login_user 函数来登入他们。例如:
@app.route("/login", methods=["GET", "POST"])
def login():
form = LoginForm()
if form.validate_on_submit():
# login and validate the user...
login_user(user)
flash("Logged in successfully.")
return redirect(request.args.get("next") or url_for("index"))
return render_template("login.html", form=form)
就这么简单。你可以之后通过 current_user 代理访问已登入的用户。需要用户登入 的视图可以用 login_required 装饰器来装饰:
@app.route("/settings")
@login_required
def settings():
pass
当用户要登出时:
@app.route("/logout")
@login_required
def logout():
logout_user()
return redirect(somewhere)
他们会被登出,且他们会话产生的任何 cookie 都会被清理干净。
用于表示用户的类需要实现这些方法:
要简便地实现用户类,你可以从 UserMixin 继承,它提供了对所有这些方法的默认 实现。(虽然这不是必须的。)
默认,在用户未登入的情况下试图访问一个 login_required 视图,Flask-Login 会 闪现一条消息并把他们重定向到登入视图。(如果未设定登入视图,会以 401 错误退 出。)
登入视图的名称可以设置为 LoginManager.login_view 。例如:
login_manager.login_view = "users.login"
默认闪现的消息是 Please log in to access this page. 要自定义消息,设置LoginManager.login_message:
login_manager.login_message = u"Bonvolu ensaluti por uzi tio paĝo."
要自定义消息的分类,设置 LoginManager.login_message_category:
login_manager.login_message_category = "info"
当重定向到登入视图,它的请求字符串中会有一个 next 变量,值为用户之前试图 访问的页面。
如果你想要进一步自定义登入过程,用 LoginManager.unauthorized_handler 装饰 一个函数:
@login_manager.unauthorized_handler
def unauthorized():
# do stuff
return a_response
默认,当用户还没有登入时, current_user 被设置为一个 AnonymousUser 对象。 它包含下列属性:
如果你有自定义匿名用户的需求(例如需要一个权限域),你可以向 LoginManager 提供一个创建匿名用户的回调(类或工厂函数):
login_manager.anonymous_user = MyAnonymousUser
“记住我”功能的实现很棘手。尽管如此,Flask-Login 几乎透明地实现了这——只需要向 login_user 调用传递 remember=True 。一个 cookie 就会存储在用户的电脑上, 且之后如果会话中没有用户 ID,Flask-Login 会自动从那个 cookie 上恢复用户 ID。 这个 cookie 是防篡改的,所以如果用户篡改了它(插入其它用户的 ID 来替代自己 的),这个 cookie 只不过会被拒绝,就如同没有一样。
该层功能是被自动实现的。但你能(且应该,如果你的应用处理任何敏感的数据)提供 额外基础工作来增强你记住的 cookie 的安全性。
使用用户 ID 作为记住的令牌值不一定是安全的。更安全的方法是使用用户名和密 码联合的 hash 值,或类似的东西。要添加一个额外的令牌,向你的用户对象添加 一个方法:
相应地,你应该在 LoginManager 上设置一个 token_loader 函数, 它接受令牌(存储在 cookie 中)作为参数并返回合适的 User 对象。
make_secure_token 函数用于便利创建认证令牌。它会连接所有的参数,然后用应用的 密钥来 HMAC 它确保最大的密码学安全。(如果你永久地在数据库中存储用户令牌,那么 你会希望向令牌中添加随机数据来阻碍猜测。)
如果你的应用使用密码来验证用户,在认证令牌中包含密码(或你应使用的加盐值的密码 hash )能确保若用户更改密码,他们的旧认证令牌会失效。
当用户登入,他们的会话被标记为“活跃”,这表明他们确实在那个会话中通过验证。当 他们的会话被销毁且他们使用“记住我” cookie 重新登入,它会被标记为“非活跃”。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 的细节可以在应用设置中定义。
REMEMBER_COOKIE_NAME | 存储“记住我”信息的 cookie 名。 默认值:remember_token |
REMEMBER_COOKIE_DURATION | Cookie 过期时间,为一个 datetime.timedelta 对 象。 默认值: 365 天(一非闰阳历年) |
REMEMBER_COOKIE_DOMAIN | 如果“记住我” cookie 应跨域,在此处设置域名值(即 .example.com 会允许 example 下所有子域 名)。 默认值: None |
当上述特性保护“记住我”令牌免遭 cookie 窃取时,会话 cookie 仍然是脆弱的。 Flask-Login 包含了会话保护来帮助阻止用户会话被盗用。
你可以在 LoginManager 上和应用配置中配置会话保护。如果它被启用,它可以在basic 或 strong 两种模式中运行。要在 LoginManager 上设置它,设置session_protection 属性为 "basic" 或 "strong":
login_manager.session_protection = "strong"
或禁用它:
login_manager.session_protection = None
默认,它被激活为 "basic" 模式。它可以在应用配置中设定 SESSION_PROTECTION 为 None 、 "basic" 或 "strong" 来禁用。
当启用了会话保护,每个请求,它生成一个用户电脑的标识(基本上是 IP 地址和 User Agent 的 MD5 hash 值)。如果会话不包含相关的标识,则存储生成的。如果 存在标识,则匹配生成的,之后请求可用。
在 basic 模式下或会话是永久的,如果该标识未匹配,会话会简单地被标记为非活 跃的,且任何需要活跃登入的东西会强制用户重新验证。(当然,你必须已经使用了活 跃登入机制才能奏效。)
在 strong 模式下的非永久会话,如果该标识未匹配,整个会话(记住的令牌如果存 在,则同样)被删除。
该文档由 Flask-Login 的源码自动生成。
This object is used to hold the settings used for logging in. Instances of LoginManager are not bound to specific apps, so you can create one in the main body of your code and then bind it to your app in a factory function.
Deprecated
This is called when the user is required to log in. If you register a callback with unauthorized_handler, then it will be called. Otherwise, it will take the following actions:
If login_view is not defined, then it will simply raise a 401 (Unauthorized) error instead.
This should be returned from a view or before/after_request function, otherwise the redirect will have no effect.
This is called when the user is logged in, but they need to be reauthenticated because their session is stale. If you register a callback with needs_refresh_handler, then it will be called. Otherwise, it will take the following actions:
If refresh_view is not defined, then it will simply raise a 403 (Forbidden) error instead.
This should be returned from a view or before/after_request function, otherwise the redirect will have no effect.
常规配置
This sets the callback for reloading a user from the session. The function you set should take a user ID (a unicode) and return a user object, or None if the user does not exist.
Parameters: | callback – The callback for retrieving a user object. |
---|
This sets the callback for loading a user from an authentication token. The function you set should take an authentication token (a unicode, as returnedby a user's `get_auth_token method) and return a user object, or None if the user does not exist.
Parameters: | callback – The callback for retrieving a user object. |
---|
一个生成匿名用户的类或工厂函数,匿名用户在无人登入的时候使用。
unauthorized 配置
当用户需要登入的时候跳转到的视图的名字。(如果你的认证机构在应用之外, 也可以是一个绝对 URL。)
当用户重定向到登入页面时要闪现的消息。
This will set the callback for the unauthorized method, which among other things is used by login_required. It takes no arguments, and should return a response to be sent to the user instead of their normal view.
Parameters: | callback – The callback for unauthorized users. |
---|
needs_refresh 配置
当用户需要重新验证时跳转到的视图的名称。
当用户重定向到重验证页面时闪现的消息。
This will set the callback for the needs_refresh method, which among other things is used by fresh_login_required. It takes no arguments, and should return a response to be sent to the user instead of their normal view.
Parameters: | callback – The callback for unauthorized users. |
---|
当前用户的代理。
This returns True if the current login is fresh.
Logs a user in. You should pass the actual user object to this. If the user’s is_active method returns False, they will not be logged in unless force is True.
This will return True if the log in attempt succeeds, and False if it fails (i.e. because the user is inactive).
Parameters: |
|
---|
Logs a user out. (You do not need to pass the actual user.) This will also clean up the remember me cookie if it exists.
This sets the current session as fresh. Sessions become stale when they are reloaded from a cookie.
If you decorate a view with this, it will ensure that the current user is logged in and authenticated before calling the actual view. (If they are not, it calls the unauthorized callback.) For example:
@app.route("/post")
@login_required
def post():
pass
If there are only certain times you need to require that your user is logged in, you can do so with:
if not current_user.is_authenticated():
return current_app.login_manager.unauthorized()
(which is essentially the code that this function adds to your views).
Parameters: | fn – The view function to decorate. |
---|
If you decorate a view with this, it will ensure that the current user’s login is fresh - i.e. there session was not restored from a “remember me” cookie. Sensitive operations, like changing a password or e-mail, should be protected with this, to impede the efforts of cookie thieves.
If the user is not authenticated, LoginManager.unauthorized is called as normal. If they are authenticated, but their session is not fresh, it will call LoginManager.needs_refresh instead. (In that case, you will need to provide a refresh_view.)
Parameters: | fn – The view function to decorate. |
---|
This provides default implementations for the methods that Flask-Login expects user objects to have.
Assuming that the user object has an id attribute, this will take that and convert it to unicode.
Returns True.
Returns False.
Returns True.
This is the default object for representing an anonymous user.
Creates a URL for redirecting to a login page. If only login_view is provided, this will just return the URL for it. If next_url is provided, however, this will append a next=URL parameter to the query string so that the login view can redirect back to that URL.
Parameters: |
|
---|
This will create a secure token that you can use as an authentication token for your users. It uses heavy-duty HMAC encryption to prevent people from guessing the information. (To make it even more effective, if you will never need to regenerate the token, you can pass some random data as one of the arguments.)
Parameters: |
|
---|
欲知在代码中如何使用这些信号,请查阅 Flask 文档的信号部分 。
当一个用户登入的时候发出。除应用(信号的发送者)之外,它还传递正登 入的用户 user 。
当一个用户登出的时候发出。除应用(信号的发送者)之外,它还传递正登 出的用户 user 。
当用户的登入被证实,把它标记为活跃的。(它不用于常规登入的调用。) 它不接受应用以外的任何其它参数。
当 LoginManager 上的 unauthorized 方法被调用时发出。它不接受应用 以外的任何其它参数。
当 LoginManager 上的 needs_refresh 方法被调用时发出。它不接受应用 以外的任何其它参数。
当会话保护起作用时,且会话被标记为非活跃或删除时发出。它不接受应用以外 的任何其它参数。