首页 > 解决方案 > 带有 SQL 连接的 Python Flask

问题描述

from flask import Flask, render_template, request, redirect, url_for, session
from flask_mysqldb import MySQL
from cryptography.fernet import Fernet
import MySQLdb.cursors
import bcrypt

app = Flask(__name__)
app.secret_key = 'your secret key'


# Enter your database connection details below
app.config['MYSQL_HOST'] = 'host'
app.config['MYSQL_USER'] = 'root'
app.config['MYSQL_PASSWORD'] = 'password'
app.config['MYSQL_DB'] = 'pythonlogin'

mysql = MySQL(app)

@app.route('', methods=['GET', 'POST'])
def password_reset():
    msg = 'asd'
    # Check if "username", "password" and "email" POST requests exist (user submitted form)
    if request.method == 'POST' and 'username' in request.form and 'password' in request.form and 'new_password' in request.form and 'email' in request.form:
        # Create variables for easy access
        username = request.form['username']
        password = request.form['password']
        new_password = request.form['new_password']
        email = request.form['email']

        #check if the account exist in the database
        cursor = mysql.connection.cursor(MySQLdb.cursors.DictCursor)
        cursor.execute( "SELECT * FROM accounts WHERE username = %s", (username,))
        account = cursor.fetchall()

        #if the account exist in database
        #the code goes in here
        if account:
            if account['username'] == session['username']:
                salt = bcrypt.gensalt(rounds=16)
                hash_password = bcrypt.hashpw(new_password.encode(), salt)

                sql = "UPDATE accounts SET password = %s WHERE username = %s "
                val = (hash_password, username)
                cursor.execute(sql, val)

                mysql.connection.commit()

                msg = "You have successfully changed the password! "

    elif request.method == 'POST':
        # Form is empty... (no POST data)
        return 'Please fill out the form!'
        # Show registration form with message (if any)

    return render_template('password_reset.html', msg=msg)

嗨,我正在使用 SQL 连接来执行此操作,我正在尝试重置用户的密码,用户在其中输入用户名、旧密码、新密码和电子邮件。然后我尝试根据用户在表单中输入的内容获取用户信息。

例如用户在表单中输入'john',并且该表单在那里检查数据库中是否有任何用户名'john',然后如果数据库中有'john',我的python代码应该替换数据库中的旧密码和用户在表单中输入的新密码

我所做的代码无法将数据库中的用户名与用户在表单中输入的内容进行比较。请帮忙

标签: pythonmysqldatabaseauthenticationflask

解决方案


一般来说,这是做应用程序(硬编码语句......)的非常古老的学校,SQL而不是推荐的现代flask应用程序方法。有很多3rd packages(有据可查的)可以使您的应用程序非常容易开发、健壮甚至更安全。我会向你推荐那些常用的第三个包:

  • Flask-SQLAlchemy对于 sql 和模型..
  • Flask-WTForms对于表格
  • Flask-Login用于认证/注册

在审查的代码下方:

from flask import Flask, flash, render_template, request, redirect, url_for, session
from flask_mysqldb import MySQL
from cryptography.fernet import Fernet
import MySQLdb.cursors
import bcrypt
import re 

app = Flask(__name__)
app.secret_key = 'your secret key'

# Enter your database connection details below
app.config['MYSQL_HOST'] = 'host'
app.config['MYSQL_USER'] = 'root'
app.config['MYSQL_PASSWORD'] = 'password'
app.config['MYSQL_DB'] = 'pythonlogin'

mysql = MySQL(app)

# add route name 
@app.route('/reset-password', methods=['GET', 'POST'])
def password_reset():
    if request.method == 'POST':

        # since username and email are uniques for any given account, you can use one of them or 
        # even better, using only the 'username' field, the user can enter his username or email
        # and then check wether the input of 'username' field is a username or an email (with 
        # simple regexp or 3rd package) so you can make the form more compact and more UI/UX friendly. 

        username     = request.form['username']  # as label for this field : "enter your usernme or email")
        password     = request.form['password']
        new_password = request.form['new_password']
        email        = request.form['email']
        
        # flag to check errors
        error = None

        # check if the 'reset password' form is filled and all parameters are posted
        if not username:
            error = "Username is required."
        elif not password:
            error = "Password is required."
        elif not new_password:
            error = "New Password is required."
        elif not email:
            error = "Email is required."
        elif not re.search('^[a-z0-9]+[\._]?[a-z0-9]+[@]\w+[.]\w{2,3}$', email):
            error = "Email is not valid."


        if error is None:
            # check if the account exist in the database
            cursor = mysql.connection.cursor(MySQLdb.cursors.DictCursor)
            cursor.execute( "SELECT * FROM accounts WHERE username = %s OR email = %s", (username, email))
            account = cursor.fetchone()  # to get the first record

            # if the account exist in database
            # the code goes in here
            if account:
                salt = bcrypt.gensalt(rounds=16)
                hash_password = bcrypt.hashpw(new_password.encode(), salt)
                
                sql = "UPDATE accounts SET password = %s WHERE username = %s "
                val = (hash_password, username)
                cursor.execute(sql, val)
                
                mysql.connection.commit()

                flash("You have successfully changed the password!", "success")

                if account['username'] == session['username']:  # if the user is already logged in
                    return redirect(url_for("dashbord"))  # redirect to dashboard
                return redirect(url_for("auth.login"))  # if not logged in, redirect him to login page 

            else:
                error = "The username / email don't match our records."

        # you don't need to pass the error / success mesaages to render_templte, use flash()
        # you can add an extra parmeter 'success' or 'error' to make difference and disply 
        # properly the right 'alert' message (if you re using Bootstrap for e.g)
        flash(error, 'error')

    return render_template('password_reset.html')

在您的主布局中使用下面的代码flash()根据它们的类别显示消息successerror

  {% with messages = get_flashed_messages(with_categories=true) %}
    {% if messages %}
      {% for category, message in messages %}
      <div class="alert alert-{% if category == 'error' %}danger{% else %}{{ category }}{% endif %} alert-dismissible fade show rounded-0" role="alert">
        <strong class="text-uppercase">{{ category }}!</strong> {{ message }}
        <button type="button" class="close" data-dismiss="alert" aria-label="Close">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
      {% endfor %}
    {% endif %}
  {% endwith %}

最后,有许多 github 存储库用于入门Flask应用程序,您可以参考下一个项目的主题,例如: https ://github.com/hack4impact/flask-base


推荐阅读