使用 werkzeug 安全地处理密码
假设我们要实现一个登录注册的功能,最简单的方式是先创建一个表,有 username 和 password 字段,然后再编写相应的登录和注册接口。
创建表
以下是一个简单的例子,展示了如何创建一个用户表并定义一些基本的操作:
python
import sqlite3
def create_connection(db_file):
""" 创建数据库连接 """
conn = None
try:
conn = sqlite3.connect(db_file)
return conn
except Exception as e:
print(e)
return conn
def create_table(conn):
""" 创建一个表 """
try:
cursor = conn.cursor()
cursor.execute("""CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY,
username TEXT NOT NULL,
password TEXT NOT NULL
);""")
conn.commit()
except Exception as e:
print(e)
def add_user(conn, username, password):
""" 向用户表中添加一个新用户 """
try:
cursor = conn.cursor()
cursor.execute("INSERT INTO users (username, password) VALUES (?, ?)", (username, password))
conn.commit()
except Exception as e:
print(e)
def main():
database = "users.db"
# 创建数据库连接
conn = create_connection(database)
# 创建表
if conn is not None:
create_table(conn)
# 添加用户示例
add_user(conn, 'username1', 'password1')
else:
print("无法创建数据库连接。")
if __name__ == '__main__':
main()
注意,这个示例中使用明文存储密码,这在实际应用中是不安全的。因此,应该使用像 werkzeug.security
中的 generate_password_hash
和 check_password_hash
这样的方法来安全地处理密码。
- 安装 Werkzeug:
python
pip install Werkzeug
- 修改添加用户函数:使用
generate_password_hash
来存储密码的哈希值,而不是明文密码。 - 创建一个验证用户的函数:使用
check_password_hash
来验证提交的密码是否与存储的哈希匹配。
python
import sqlite3
from werkzeug.security import generate_password_hash, check_password_hash
def create_connection(db_file):
""" 创建数据库连接 """
# ... 代码不变 ...
def create_table(conn):
""" 创建一个表 """
# ... 代码不变 ...
def add_user(conn, username, password):
""" 向用户表中添加一个新用户 """
hashed_password = generate_password_hash(password)
try:
cursor = conn.cursor()
cursor.execute("INSERT INTO users (username, password) VALUES (?, ?)", (username, hashed_password))
conn.commit()
except Exception as e:
print(e)
def verify_user(conn, username, password):
""" 验证用户凭据 """
try:
cursor = conn.cursor()
cursor.execute("SELECT password FROM users WHERE username = ?", (username,))
stored_password = cursor.fetchone()
if stored_password and check_password_hash(stored_password[0], password):
return True
else:
return False
except Exception as e:
print(e)
return False
# main 函数和其他部分的代码不变
接口编写
首先,定义 User 模型
python
from database import db
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True, nullable=False)
password = db.Column(db.String(120), nullable=False)
def to_dict(self):
return {
'id': self.id,
'username': self.username
# 注意:不要返回密码
}
然后,在 Flask 应用中添加注册和登录路由处理函数:
python
from flask import Flask, request, jsonify
from werkzeug.security import generate_password_hash, check_password_hash
# ... 其他导入 ...
# ... Flask 应用的其他部分 ...
@app.route('/api/register', methods=['POST'])
def register():
data = request.get_json()
# 确认数据有效性
username = data.get('username')
password = data.get('password')
if not username or not password:
return jsonify({'message': 'Missing username or password'}), 400
# 检查用户名是否已存在
if User.query.filter_by(username=username).first():
return jsonify({'message': 'Username already exists'}), 400
# 创建新用户
hashed_password = generate_password_hash(password)
new_user = User(username=username, password=hashed_password)
db.session.add(new_user)
db.session.commit()
return jsonify({'message': 'User created successfully', 'user': new_user.to_dict()}), 201
@app.route('/api/login', methods=['POST'])
def login():
data = request.get_json()
username = data.get('username')
password = data.get('password')
if not username or not password:
return jsonify({'message': 'Missing username or password'}), 400
# 检查用户是否存在
user = User.query.filter_by(username=username).first()
if user and check_password_hash(user.password, password):
# 在这里,你应该生成并返回一个认证令牌
return jsonify({'message': 'Login successful', 'user': user.to_dict()}), 200
else:
return jsonify({'message': 'Invalid credentials'}), 401
# ... Flask 应用的其他部分 ...
if __name__ == '__main__':
app.run(debug=True)
注意
使用 Werkzeug 的 generate_password_hash
函数对密码进行哈希处理后,原始密码将不再可见,因此不再存储明文密码。这是哈希算法的一种基本原则,密码不应该以明文形式存储,以提高安全性。
因此,一旦密码被哈希处理,就不再能够直接查看密码的明文值。验证密码时,您将使用 check_password_hash
函数来比较哈希值,而不是查看明文密码。
当然,我们可以使用 Werkzeug 验证密码:、
python
from werkzeug.security import generate_password_hash, check_password_hash
# 生成哈希密码
password = "userpassword123"
hashed_password = generate_password_hash(password)
# 检查密码
user_input_password = "userpassword123" # 用户输入的密码
if check_password_hash(hashed_password, user_input_password):
print("密码正确")
else:
print("密码错误")
在上述示例中,generate_password_hash 用于创建哈希密码,而 check_password_hash 用于验证用户提供的密码是否与哈希密码匹配。由于哈希是单向的,所以无法从哈希密码还原出明文密码。