MST

星途 面试题库

面试题:Python Flask应用如何实现安全的用户认证与授权

使用Flask构建一个Web应用,要求实现用户的注册、登录功能,并且在登录后对不同权限的用户进行授权,只有具有特定权限的用户才能访问某些特定的路由。请描述实现思路,并给出关键代码片段,同时说明在这个过程中如何保障用户密码的安全存储。
24.7万 热度难度
编程语言Python

知识考点

AI 面试

面试题答案

一键面试

实现思路

  1. 用户注册:创建注册页面表单,接收用户输入的信息(如用户名、密码等),验证信息合法性后将用户信息存储到数据库。
  2. 用户登录:创建登录页面表单,接收用户输入的用户名和密码,与数据库中存储的信息进行比对,验证成功则生成并返回认证令牌(如JWT)。
  3. 权限授权:在数据库中为每个用户记录权限信息。在需要权限控制的路由上,通过中间件或装饰器检查用户令牌,解析出用户权限,判断是否有权限访问该路由。
  4. 密码安全存储:使用强哈希算法(如bcrypt)对用户密码进行哈希处理后存储,验证密码时使用相同算法比对哈希值。

关键代码片段

  1. 安装必要的库
pip install flask flask_sqlalchemy flask_bcrypt flask_jwt_extended
  1. 定义数据库模型
from flask_sqlalchemy import SQLAlchemy
from flask_bcrypt import Bcrypt

db = SQLAlchemy()
bcrypt = Bcrypt()

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(50), unique=True, nullable=False)
    password = db.Column(db.String(100), nullable=False)
    role = db.Column(db.String(20), nullable=False)  # 权限字段
  1. 用户注册
from flask import Flask, request, jsonify

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] ='sqlite:///users.db'
db.init_app(app)
bcrypt.init_app(app)

@app.route('/register', methods=['POST'])
def register():
    data = request.get_json()
    hashed_password = bcrypt.generate_password_hash(data['password']).decode('utf-8')
    new_user = User(username=data['username'], password=hashed_password, role=data['role'])
    db.session.add(new_user)
    db.session.commit()
    return jsonify({'message': 'User registered successfully'}), 201
  1. 用户登录
from flask_jwt_extended import create_access_token

@app.route('/login', methods=['POST'])
def login():
    data = request.get_json()
    user = User.query.filter_by(username=data['username']).first()
    if user and bcrypt.check_password_hash(user.password, data['password']):
        access_token = create_access_token(identity=user.id)
        return jsonify({'access_token': access_token}), 200
    return jsonify({'message': 'Invalid credentials'}), 401
  1. 权限控制装饰器
from functools import wraps
from flask_jwt_extended import get_jwt_identity, verify_jwt_in_request
from flask import abort

def requires_role(role):
    def wrapper(fn):
        @wraps(fn)
        def decorator(*args, **kwargs):
            verify_jwt_in_request()
            user_id = get_jwt_identity()
            user = User.query.get(user_id)
            if user.role != role:
                abort(403)
            return fn(*args, **kwargs)
        return decorator
    return wrapper
  1. 需要权限的路由
@app.route('/admin/dashboard', methods=['GET'])
@requires_role('admin')
def admin_dashboard():
    return jsonify({'message': 'This is an admin - only dashboard'}), 200

密码安全存储

  1. 哈希处理:使用bcrypt.generate_password_hash对用户输入的密码进行哈希处理,存储到数据库的是哈希后的字符串,而不是明文密码。
  2. 密码验证:在用户登录时,使用bcrypt.check_password_hash比对用户输入的密码和数据库中存储的哈希值,验证用户身份。