管理员(仅限)注册用户,Flask-Security

时间:2015-06-29 11:23:12

标签: python flask flask-wtforms flask-login flask-security

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

success: function () {$(btnSelector).hide();}

这将创建成功限制为具有Admin角色的帐户的门户。我不确定如何继续这里,因为Flask-security没有内置的方法来启用我想要做的事情。

我已经覆盖RegisterForm以通过regexp强制执行密码规则:

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

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

我看过的有用的东西:

  1. 在flask-security / views.py中,有一个被遗忘的密码:

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

    的代码
    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'))
    
  3. 我想以某种方式将这两者结合起来,以便在提交表格时提供唯一字段" Email" at' / adminregister'电子邮件在数据库中添加了一个安全的随机密码,电子邮件地址会发送一封电子邮件,其中包含更改密码的链接(理想情况下是消息说明)。我甚至不确定在哪里添加这样的代码,因为没有什么可以特别覆盖,特别是因为我找不到覆盖RegisterForm以获得FEWER字段和相同功能的方法。

    我的代码结构符合flask-security文档quickstart

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

4 个答案:

答案 0 :(得分:1)

我最终使用了如下工作:

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

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

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

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

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

  5. 如果有人想出一种更直接的方式,我会很感激。如果有人遇到同样的问题,我会把它留在这里。

答案 1 :(得分: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()

这会停用所有新注册的用户。

答案 2 :(得分:0)

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

首先导入register_user

from flask_security.registerable import register_user

然后,因为您不希望任何人注册,请确保禁用注册(虽然禁用是默认设置,因此您可以省略),因为您要发送确认电子邮件,启用可确认,并且可以更改用户更改其密码< / p>

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)

答案 3 :(得分:0)

另请参见flask-security - admin create user, force user to choose password

这是我在反复摇瓶安全后发现的另一种解决方案。我做了一个管理员创建用户表单,并在数据库中创建用户后简单地添加了以下代码:

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)