首页 > 解决方案 > Python Flask 函数返回网页以在 Mongodb 中请求和更新密码

问题描述

在启用重置密码(令牌)链接的函数中...我需要显示一个网页/表单,我可以使用它来获取用户密码,使用 bcrypt 生成密码哈希,然后在 MongoDB 中查找并更新密码。

我的主要问题是在函数中显示网页/表单。我在第 5 行收到服务器错误

from flask import Flask, jsonify, request, json, url_for, render_template, flash
from flask_mail import Mail, Message
from itsdangerous import URLSafeTimedSerializer, SignatureExpired
from flask_pymongo import PyMongo
from flask_bcrypt import Bcrypt 


@app.route('/users/reset_password', methods=["GET", "POST"])
def reset_password():
    users = mongo.db.users
    email = request.get_json()['email']
    user_exist = users.find_one({'email': email})

    if user_exist:
        token = s.dumps(email, salt='reset-password-salt')
        msg = Message('Password Reset', sender='admin@exib.com', recipients=[email])
        link = url_for('password_reset', token=token, _external=True)
        msg.body = 'Your password reset link is {}'.format(link)
        mail.send(msg)
        result = jsonify({'message': 'password reset link has been sent to your email'})
    else: 
        result = jsonify({'message': 'this user does not exist'}), 400
    return result

@app.route('/users/password_reset/<token>')
def password_reset(token):
    try:
        email = s.loads(token, salt='reset-password-salt', max_age=3600)
        users = mongo.db.users
        password = bcrypt.generate_password_hash(request.form['password']).decode('utf-8')# SERVER ERROR HERE
        users.find_one_and_update(
            {'email': email},
            {'$set':
                {'password': password}
            },upsert=False
        )
        ## I want to display the webform somewhere here to take just 'password' ##
    except SignatureExpired:
        return '<h1>The token is expired!</h1>'
    return passchange.html # '<h1>Password change successful!</h1>'

HTML 页面 returnpasschange.html

{% extends "layout.html" %}
{% block body %} 
<div class="container">
    <div class="row">
        <div class="col-md-4 col-md-offset-4">
            <form method=POST action="{{ url_for('password_reset') }}">
                <!-- <div class="form-group">
                    <label for="exampleInputOldPassword1">Old Password</label>
                    <input type="password" class="form-control" name="oldPassword" placeholder="OldPassword">
                </div> -->
                <div class="form-group">
                    <label for="exampleInputPassword1">Password</label>
                    <input type="password" class="form-control" name="password" placeholder="Password">
                </div>
                <button type="submit" class="btn btn-primary btn-block">Change Password</button>
            </form>
            <br>
        </div>
    </div>
</div>

标签: pythonmongodbflaskpymongo

解决方案


主要问题是您没有在password_reset方法中检查请求的类型。因此,每次,无论GETPOST或任何其他请求类型,它都在执行该方法。但是,request.form字典可POST应要求提供。如果您正在执行GET请求,这将导致异常。

因此,我建议您将其主体更改为如下所示:

@app.route('/users/password_reset/<token>', methods=['GET', 'POST'])
def password_reset(token):
    if request.method == 'POST':
        # Do something
    elif request.method == 'GET'
        # Do something

确保在检索表单值时,像这样检索它request.form.get('password'),而不是request.form['password']. 这是因为,有时这些字段可能不存在,并且会导致另一个异常。因此,前者就像是检索所需值的安全方法。

name当您从中检索值时,还要检查该字段的属性是否与键匹配request.form


推荐阅读