【问题标题】:Python Flask with SQL connection带有 SQL 连接的 Python Flask
【发布时间】:2020-06-22 10:47:37
【问题描述】:
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代码应将数据库中的旧密码替换为用户在表单中输入的新密码

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

【问题讨论】:

    标签: python mysql database authentication flask


    【解决方案1】:

    这是一个非常古老的应用程序(硬编码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')
    

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

      {% 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

    【讨论】:

    • 非常感谢您的帮助和评论,我这样做是因为我的学校要求,所以我别无选择,只能申请。
    • @LiangJin 没问题,反正Flask 官方教程(github.com/pallets/flask/tree/1.1.2/examples/tutorial) 也是老办法。如果你觉得我的回答对你的情况有用,你介意给它一个绿色的勾吗?
    【解决方案2】:

    我认为您需要稍微更改一下代码

    该方法获取查询结果集的所有(或所有剩余)行并返回元组列表。如果没有更多行可用,则返回一个空列表。 所以 fetchall 会给出类似 [(),()] 你需要的第一个元素,

    或者你可以使用 cursor.fetchone() 给你一条记录或 None 你会得到这样的结果一个像这样的行的元组()

    (1, 'Emma', 'emma@pynative.com', 'asdasd',)

    并且您需要设置正确的索引才能从数据库中访问您的用户名,例如 account_name = account[your_acccount_name_index]

    并匹配account_name == username == session['username']

    【讨论】:

      猜你喜欢
      • 2021-01-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-30
      相关资源
      最近更新 更多