How to implement user_loader callback in Flask-Login

前端 未结 3 2211
被撕碎了的回忆
被撕碎了的回忆 2021-01-30 16:57

I\'m attempting to use Flask and the Flask-Login extension to implement user authentication in a Flask app. The goal is to pull user account information from a database and then

相关标签:
3条回答
  • 2021-01-30 17:47

    Here is my code, another User as data mapping object provide query_pwd_md5 method.

    User login:

    @app.route('/users/login', methods=['POST'])
    def login():
        # check post.
        uname = request.form.get('user_name')
        request_pwd = request.form.get('password_md5')
    
        user = User()
        user.id = uname
    
        try:
            user.check_pwd(request_pwd, BacktestUser.query_pwd_md5(
                uname, DBSessionMaker.get_session()
            ))
            if user.is_authenticated:
                login_user(user)
                LOGGER.info('User login, username: {}'.format(user.id))
                return utils.serialize({'userName': uname}, msg='login success.')
            LOGGER.info('User login failed, username: {}'.format(user.id))
            return abort(401)
        except (MultipleResultsFound, TypeError):
            return abort(401)
    

    User class:

    class User(UserMixin):
    """Flask-login user class.
    """
    
    def __init__(self):
        self.id = None
        self._is_authenticated = False
        self._is_active = True
        self._is_anoymous = False
    
    @property
    def is_authenticated(self):
        return self._is_authenticated
    
    @is_authenticated.setter
    def is_authenticated(self, val):
        self._is_authenticated = val
    
    @property
    def is_active(self):
        return self._is_active
    
    @is_active.setter
    def is_active(self, val):
        self._is_active = val
    
    @property
    def is_anoymous(self):
        return self._is_anoymous
    
    @is_anoymous.setter
    def is_anoymous(self, val):
        self._is_anoymous = val
    
    def check_pwd(self, request_pwd, pwd):
        """Check user request pwd and update authenticate status.
    
        Args:
            request_pwd: (str)
            pwd: (unicode)
        """
        if request_pwd:
            self.is_authenticated = request_pwd == str(pwd)
        else:
            self.is_authenticated = False
    
    0 讨论(0)
  • 2021-01-30 17:49

    I do share your concerns Edmond: hitting database each time when one needs to know user's role or name is insane. Best way would be to store your User object in session or even application-wide cache which gets updated from the DB each couple of minutes. I personally use Redis for that (that way website can be run by multiple threads/processes while using single cache entry point). I just make sure Redis is configured with password and non-default port, and any confidential data (like user hashes etc) are stored there in an encrypted form. Cache can be populated by a separate script running on specified interval, or separate thread can be spawned in Flask. Note: Flask-Session can be also configured to use (the same) redis instance to store session data, in that case instance with 'bytes' datatype will be needed, for a regular cache you might often go with instance type which automatically translates bytes into strings (decode_responses=True).

    0 讨论(0)
  • 2021-01-30 18:04

    You will need to load the user object from the DB upon every request. The strongest reason for that requirement is that Flask-Login will check the authentication token every time to ensure its continuing validity. The calculation of this token may require parameters stored on the user object.

    For example, suppose a user has two concurrent sessions. In one of them, the user changes their password. In subsequent requests, the user must be logged out of the second session and forced to login anew for your application to be secure. Think of the case where the second session is stolen because your user forgot to log out of a computer - you want a password change to immediately fix the situation. You might also want to give your admins the ability to kick a user out.

    For such forced logout to happen, the authentication token stored in a cookie must 1) be based in part on the password or something else that changes each time a new password is set; 2) be checked before running any view, against the latest known attributes of the user object - which are stored in the DB.

    0 讨论(0)
提交回复
热议问题