简体   繁体   中英

Flask-User @login_required and @roles_required not working

I am trying to use Flask-User (which incorporates Flask-Login). I would like to use the @login_required and @roles_required decorators to manage access to routes. However, it is not working.

The Flask-User documentation shows login_required being imported from flask_user , not flask_login . When imported from flask_login it works as expected, but if I switch it to be imported from flask_user it does not work. Instead, it says that an authenticated user is not signed in.

Why don't I just import from flask_login ? Well, I could, but that does not solve my other problem which is that @roles_required can only be imported from flask_user , and that does not work either (same problem as above - says that authenticated users are not signed in).

My setup is below. I would be grateful if anyone could help me out, please. I have previously had Flask User working on another app, but can't figure out what's going wrong here. At the moment, the user database is stored in an SQLite database.

config.py

# Flask-User settings
    USER_APP_NAME = "App name"      # Shown in and email templates and page footers
    USER_ENABLE_EMAIL = True        # Enable email authentication
    USER_ENABLE_USERNAME = False    # Disable username authentication
    USER_EMAIL_SENDER_NAME = USER_APP_NAME
    USER_EMAIL_SENDER_EMAIL = "email"
    USER_ENABLE_AUTH0 = True

    USER_UNAUTHENTICATED_ENDPOINT = "login"
    USER_UNAUTHORIZED_ENDPOINT = "login"

__init__.py

# Initialise flask_login
login = LoginManager(app)
login.login_view = 'login'
login.refresh_view = "login"
login.needs_refresh_message = "Please sign in again to access this page"

models.py

from andon import db, app, login
from flask_user import UserMixin, UserManager
from flask_login import current_user

@login.user_loader
def load_user(id):
    return User.query.get(int(id))

class User(db.Model, UserMixin):
    id = db.Column(db.Integer, primary_key=True)

    # User Authentication fields
    email = db.Column(db.String(255), nullable=False, unique=True)
    email_confirmed_at = db.Column(db.DateTime())
    password = db.Column(db.String(255), nullable=False)

    # User fields
    active = db.Column(db.Boolean())
    first_name = db.Column(db.String(50), nullable=False)
    last_name = db.Column(db.String(50), nullable=False)
    registered = db.Column(db.DateTime, default=datetime.utcnow)
    last_login = db.Column(db.DateTime)
    client_id = db.Column(db.Integer, db.ForeignKey('client.id', ondelete='CASCADE'))
    login_count = db.Column(db.Integer, default=0)
    invitation_token = db.Column(db.String(50))

    roles = db.relationship('Roles', secondary='user_roles')

    def check_password(self, password):
        # Check password against hash; return True or False
        return bcrypt.checkpw(password.encode('utf8'), self.password)

# Define the Role data model
class Roles(db.Model):
    id = db.Column(db.Integer(), primary_key=True)
    name = db.Column(db.String(50), nullable=False, unique=True)  # for @roles_accepted()

    def __repr__(self):
        return self.name


# Define the UserRoles association model
class UserRole(db.Model):
    __tablename__ = 'user_roles'
    id = db.Column(db.Integer(), primary_key=True)
    user_id = db.Column(db.Integer(), db.ForeignKey('user.id', ondelete='CASCADE'))
    role_id = db.Column(db.Integer(), db.ForeignKey('roles.id', ondelete='CASCADE'))

# Setup Flask-User
user_manager = UserManager(app, db, User)

main.py

from flask_login import current_user, login_user, logout_user
from flask_user import roles_required, login_required

@app.route('/test')
@login_required
def register_hub():

    return "Test"

After hours of tearing out my remaining hairs, I have found the issue. I had set USER_ENABLE_EMAIL = True , which I thought allowed flask-user to allow sign ins via email (as opposed to a username). What it actually does is require users to be email verified.

Since my user account did not have a flag saying it had been email verified, it was throwing as not having any login permissions. Annoying that flask-user does not throw a descriptive error in this circumstance, instead just saying that the user isn't signed in.

So, the fix: set USER_ENABLE_EMAIL = False , unless you want to force email verification before users have access to @login_required routes.

I couldn't write a comment to your previous answer, so I will just quote the following and expand on it:

What it actually does is require users to be email verified.

The following setting, is as you thought, will allow users to login and register with an email address

 USER_ENABLE_EMAIL = True

what you want to do on top of that is to add the next setting to disable email confirmation (confirmation emails will not be send)

USER_ENABLE_CONFIRM_EMAIL = False

UserManager Settings docs

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