Flask-login:如果login_manager的session_protection设置为"strong",请记住我不工作

Sub*_*rav 5 python flask flask-login

我正在使用flask-login在我的烧瓶应用程序中集成会话管理.但是,如果我将session_protection设置为strong,则记住我的功能不起作用,但是,如果将其设置为basic,它将完全正常.

user_loader:

@login_manager.user_loader
def load_user(email):
    user = get_user_with_email(email)
    if user:
        return User(user.id, user.email, user.role_id, user.createtime, user.updatetime)
Run Code Online (Sandbox Code Playgroud)

从数据库中获取用户:

from psycopg2.extras import NamedTupleCursor

def get_user_with_email(email):
    cursor = get_db().cursor(cursor_factory=NamedTupleCursor)
    cursor.execute('SELECT * FROM users WHERE email = %s', (email,))
    return cursor.fetchone()
Run Code Online (Sandbox Code Playgroud)

和我的用户类:

class User(UserMixin):
    def __init__(self, username, email, role_id, createtime, updatetime):
        self.username = username
        self.email = email
        self.role_id = role_id
        self.createtime = createtime
        self.updatetime = updatetime

    @property
    def password(self):
        raise AttributeError('password is not a readable property')

    @password.setter
    def password(self, password):
        self._password = generate_password_hash(password)

    def verify_password(self, password):
        return check_password_hash(self._password, password)

    @property
    def is_active(self):
        """All users are active"""
        return True

    @property
    def is_anonymous(self):
        """Always return False, anonymous users aren't supported"""
        return False

    def get_id(self):
        """Return username for flask_login to use it as user id"""
        return self.email

    @property
    def is_authenticated(self):
        """All users are authenticated"""
        return True

    def register(self, password):
        self.password = password
        # Todo: complete the registration logic

    def __repr__(self):
        return 'User(username={0}, email={1})'.format(self.username, self.email)
Run Code Online (Sandbox Code Playgroud)

我正在完成文档中提到的内容,但是当浏览器关闭时,用户仍会在强大保护的情况下注销.我不确定出了什么问题.

我要感谢任何帮助,谢谢!

mor*_*030 7

您没有做错任何事情,这是会话保护设置为强时所需的行为.

编辑:

基本上,当设置会话保护(基本或强)时,在用户登录后,会话标识符(基于用户IP和用户用户代理)被计算并存储.然后根据每个新请求计算并使用存储的版本进行检查.

浏览器重启后,为了加载用户,Flask-Login将在remember_me cookie旁边检查会话ID是否与存储值匹配.但是,由于浏览器重新启动,将不会存储会话ID值,并且此测试将不会通过.因此,这两件事之一将会发生.

  • 如果保护设置为基本,会话将被标记为不新鲜,用户将从记住我的cookie加载.

  • 如果保护设置为强,则不会加载用户并记住我将删除cookie.

如果使用基本设置,最好使用fresh_login_required来装饰处理敏感操作(例如密码更改)的视图功能.正如官方文档中所述:

flask_login.fresh_login_required(func) 如果你用这个装饰一个视图,它将确保当前用户的登录是新的 - 即他们的会话没有从'记住我'的cookie中恢复.敏感操作,如更改密码或电子邮件,应受此保护,以阻止cookie窃贼的努力.

https://flask-login.readthedocs.io/en/latest/_modules/flask_login/utils.html#fresh_login_required

  • 欢迎来到Stack Overflow!这应该是评论,而不是答案.您[赚]后可以[发表评论](http://stackoverflow.com/help/privileges/comment)(http://meta.stackexchange.com/questions/146472/what-is-the-best-足够[声誉](http://stackoverflow.com/help/whats-reputation)的方式来增加我的声誉和特权. (2认同)
  • 随时可以链接到潜在的解决方案,你可以[在链接上添加上下文](http://meta.stackoverflow.com/a/8259/169503),这样你的同行用户就会知道它是什么以及它为什么那里.如果目标站点无法访问或永久脱机,请始终引用重要链接的最相关部分.如果你这样做,这可能是一个很好的答案! (2认同)