简体   繁体   中英

Flask-login: remember me not working if login_manager's session_protection is set to “strong”

i am using flask-login to integrate session management in my flask app. But the remember me functionality doesn't work if i set the session_protection to strong , however, it works absolutely fine if it's set to 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)

to fetch user from the database:

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()

and my user class:

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)

I am doing exactly what is mentioned in the documentation, but still the user logs out when the browser closes in case of strong protection. i am not sure what's going wrong.

I would appreciate any help, thanks !

You are not doing anything wrong, that is desired behavior when session protection is set to strong.

Edit:

Basically, when session protection is set (to basic or strong), after user logs in, session identifier is computed (based on users IP and users user-agent) and stored. And it is then computed upon each new request and checked with stored version.

After browser restart in order to load a user Flask-Login will check, beside the remember_me cookie, if the session id matches stored value. But since browser is restarted there won't be stored session id value and this test won't pass.So one of these two things will happen then.

  • If the protection is set to basic, session will be flagged as not fresh and user will be loaded from remember me cookie.

  • If the protection is set to strong the user won't be loaded and remember me cookie will be deleted.

It is good practice, if basic setting is used, to decorate view function that handles sensitive operations(such as password change) with fresh_login_required. As stated in the official docs:

flask_login.fresh_login_required(func) If you decorate a view with this, it will ensure that the current user's login is fresh - ie their 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.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM