3

我目前正在使用 Flask-Security(包括 Flask-WTForms、Flask-SQLalchemy 和 Flask-Login)为 web 应用程序构建登录。我已经能够相当轻松地设置我的大部分登录流程,包括忘记密码;但是我想这样做,以便用户注册的唯一方法是通过只有管理员可以访问的页面。我设法配置了角色(管理员、用户)并设置了以下视图:

@app.route('/adminregister')
@roles_accepted('admin')
def adminregister():
    return render_template('*')

这将创建成功限制为具有管理员角色的帐户的门户。但是,我不确定如何在这里进行,因为 Flask-security 没有内置的方法来启用我正在尝试做的事情。

我已经覆盖了 RegisterForm 以通过正则表达式强制执行密码规则:

# fixed register form
class ExtendedRegisterForm(RegisterForm):
password = TextField('Password', [validators.Required(), validators.Regexp(r'(?=.*?[0-9])(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[$-/:-?{-~!"^_`\[\]])')])

基本上我想要一个位于 /adminregister 的表单,当管理员访问该表单时,它允许输入电子邮件地址,此时首先在数据库中使用随机且安全的密码创建用户,然后执行类似的过程发生忘记密码并创建 1 次密码代码以重置密码。

我看过的有用的东西:

  1. 在 flask-security/views.py 中有忘记的密码代码:

    def forgot_password():
    """View function that handles a forgotten password request."""
    
    form_class = _security.forgot_password_form
    
    if request.json:
        form = form_class(MultiDict(request.json))
    else:
        form = form_class()
    
    if form.validate_on_submit():
        send_reset_password_instructions(form.user)
        if request.json is None:
            do_flash(*get_message('PASSWORD_RESET_REQUEST', email=form.user.email))
    
    if request.json:
        return _render_json(form, include_user=False)
    
    return _security.render_template(config_value('FORGOT_PASSWORD_TEMPLATE'),
                                 forgot_password_form=form,
                                 **_ctx('forgot_password'))
    
  2. 在 flask_security/registerable.py 中有 register_user 的代码

    def register_user(**kwargs):
    confirmation_link, token = None, None
    kwargs['password'] = encrypt_password(kwargs['password'])
    user = _datastore.create_user(**kwargs)
    _datastore.commit()
    
    if _security.confirmable:
        confirmation_link, token = generate_confirmation_link(user)
        do_flash(*get_message('CONFIRM_REGISTRATION', email=user.email))
    
    user_registered.send(app._get_current_object(),
                         user=user, confirm_token=token)
    
    if config_value('SEND_REGISTER_EMAIL'):
        send_mail(config_value('EMAIL_SUBJECT_REGISTER'), user.email, 'welcome',
                  user=user, confirmation_link=confirmation_link)
    
    return user
    

我想以某种方式将这两者结合起来,以便在“/adminregister”中提交具有唯一字段“电子邮件”的表单后,电子邮件会在数据库中添加一个安全的随机密码,并且电子邮件地址会发送一封电子邮件,其中包含链接以更改密码(最好是一条消息解释)。我什至不确定我会在哪里添加这样的代码,因为没有什么可以专门覆盖,特别是因为我找不到覆盖 RegisterForm 以拥有更少的字段和相同的功能的方法。

我的代码结构与 flask-security 文档的quickstart 一致

提前感谢您提供的任何指导。

4

4 回答 4

2

我最终使用了如下解决方法:

  1. 我启用了注册,但注册视图仅限于具有管理员角色的用户。

  2. del form.password在视图中使用 -> 注册以不再发送带有密码字段的表单。

  3. 我在 .registerable 中执行了以下操作,生成了一个随机密码来填充表格。

    kwargs['password'] = encrypt_password(os.urandom(24))

  4. 管理员在注册表中输入电子邮件后,我启用了 confimable。这意味着用户会立即收到一封电子邮件,以确认他们的帐户并解释他们已经注册。确认后,他们将被重定向到忘记密码页面并要求更改密码(基于安全性限制)。

如果有人提出更直接的方法,我将不胜感激。我把这个留在这里,以防有人遇到同样的问题。

于 2015-07-05T07:39:26.527 回答
2

我知道这是一个古老的问题,但我想我有一个优雅的答案。

首先导入 register_user

from flask_security.registerable import register_user

然后,由于您不希望任何人都注册,因此请确保禁用可注册(尽管禁用是默认设置,因此您可以省略它)并且由于您要发送确认电子邮件,因此启用可确认和可更改以供用户更改密码

app.config['SECURITY_CONFIRMABLE'] = True
app.config['SECURITY_REGISTERABLE'] = False
app.config['SECURITY_RECOVERABLE'] = True

然后,您可以创建您的用户注册视图并使用所需的角色装饰它。我使用了我自己的自定义注册表单,所以我不得不加倍努力检查用户是否已经存在并相应地返回错误

@app.route('/admin/create/user', methods=['GET', 'POST'])
@roles_required('admin')
def admin_create_user():
    form = RegistrationForm(request.form)
    if request.method == 'POST' and form.validate_on_submit():
        email = form.email.data
        password = form.password.data
        user_exists = session.query(User).filter_by(email=email).first()
        if user_exists:
            form.email.errors.append(email + ' is already associated with another user')
            form.email.data = email
            email = ''
            return render_template('create-user.html', form = form)

        else:
            register_user(
                    email=email,
                    password = password)
            flash('User added successfully')
            return render_template('create-user.html', form = form)
于 2018-03-14T09:22:17.967 回答
1

注册过程会创建一个带有闪烁器的信号,您可以像这样访问它:

from flask.ext.security.signals import user_registered
@user_registered.connect_via(app)
def user_registered_sighandler(app, user, confirm_token):
    user_datastore.deactivate_user(user)
    db.session.commit()

这将停用任何新注册的用户。

于 2016-02-20T07:47:26.007 回答
1

另见烧瓶安全 - 管理员创建用户,强制用户选择密码

这是我在浏览烧瓶安全后发现的另一个解决方案。我做了一个管理员创建用户表单,在数据库中创建用户后只需添加以下代码:

from flask_security.recoverable import send_reset_password_instructions

# my code is maintains self.created_id after creating the user record
# this is due to some complex class involved which handles my crudapi stuff
# your code may vary
user = User.query.filter_by(id=self.created_id).one()
send_reset_password_instructions(user)
于 2020-01-04T18:18:43.303 回答