Python HTTP服务器添加简单用户名密码认证的三种方案

目录

[1. 基础认证原理](#1. 基础认证原理)

[2. 三种实现方案](#2. 三种实现方案)

[2.1 方案一:使用标准库手动实现](#2.1 方案一:使用标准库手动实现)

[2.2 方案二:使用Flask和flask_httpauth库](#2.2 方案二:使用Flask和flask_httpauth库)

[2.3 方案三:增强安全性(存储密码哈希)](#2.3 方案三:增强安全性(存储密码哈希))

[3. 重要安全提醒](#3. 重要安全提醒)

[4. 总结](#4. 总结)


为Python HTTP服务器添加用户名密码认证是保护内容的好方法。以下是几种从简单到实用的实现方案。

1. 基础认证原理

HTTP Basic Authentication(基础认证)的原理是:客户端请求时,服务器检查认证信息。若未提供,返回401 Unauthorized状态码和WWW-Authenticate头部,提示需要认证。浏览器会弹出对话框让用户输入用户名和密码。客户端将用户名和密码用冒号连接后,进行Base64编码,然后在下次请求的Authorization头部中发送给服务器。服务器解码并验证凭据,通过则返回资源,否则返回错误。

2. 三种实现方案

您可以根据需求选择以下方案:

方案 优点 缺点 适用场景
标准库手动实现 无需额外依赖;理解底层机制 代码量稍大;安全性需自行处理 学习原理;轻量级临时使用
Flask + flask_httpauth 代码简洁;功能完善;安全性好 需安装Flask框架 大多数需要认证的Web应用
密码哈希增强 存储更安全;防止密码泄露 增加轻微复杂度 任何存储用户密码的场景
2.1 方案一:使用标准库手动实现

这种方法直接使用Python内置的http.server模块,适合理解认证流程。

python 复制代码
from http.server import HTTPServer, BaseHTTPRequestHandler
import base64

# 预定义合法的用户名和密码
VALID_USERNAME = 'admin'
VALID_PASSWORD = 'password123'

class AuthHTTPRequestHandler(BaseHTTPRequestHandler):

    def do_GET(self):
        # 1. 调用认证检查
        if not self.authenticate():
            return  # 认证失败,方法已处理响应

        # 2. 认证成功,返回受保护的内容
        self.send_response(200)
        self.send_header('Content-type', 'text/html; charset=utf-8')
        self.end_headers()
        self.wfile.write(f'<h1>你好,{VALID_USERNAME}!认证成功。</h1>'.encode('utf-8'))

    def authenticate(self):
        """处理认证逻辑"""
        auth_header = self.headers.get('Authorization')

        # 2.1 检查请求头是否包含认证信息
        if not auth_header:
            self.send_authentication_required()  # 发送401要求认证
            return False

        try:
            # 2.2 解析和验证凭证
            auth_type, encoded_credentials = auth_header.split(' ', 1)
            if auth_type.lower() != 'basic':
                self.send_authentication_required()
                return False

            decoded_bytes = base64.b64decode(encoded_credentials)
            decoded_str = decoded_bytes.decode('utf-8')
            username, password = decoded_str.split(':', 1)

            if username == VALID_USERNAME and password == VALID_PASSWORD:
                return True  # 认证通过
            else:
                self.send_forbidden()  # 凭证错误,发送403
                return False

        except Exception as e:
            self.send_forbidden()
            return False

    def send_authentication_required(self):
        """发送401认证要求响应"""
        self.send_response(401)
        self.send_header('WWW-Authenticate', 'Basic realm="Secure Area"')
        self.send_header('Content-type', 'text/html; charset=utf-8')
        self.end_headers()
        self.wfile.write(b'<h1>401 - 需要认证</h1>')

    def send_forbidden(self):
        """发送403禁止访问响应"""
        self.send_response(403)
        self.send_header('Content-type', 'text/html; charset=utf-8')
        self.end_headers()
        self.wfile.write(b'<h1>403 - 用户名或密码错误</h1>')

if __name__ == '__main__':
    server_address = ('', 8080)
    httpd = HTTPServer(server_address, AuthHTTPRequestHandler)
    print('服务器运行在 http://localhost:8080')
    httpd.serve_forever()
2.2 方案二:使用Flask和flask_httpauth库

这是更推荐的方法,代码更简洁安全。

  1. 安装必要的库

    复制代码
    pip install Flask flask_httpauth
  2. 创建Flask应用(app.py

    python 复制代码
    from flask import Flask
    from flask_httpauth import HTTPBasicAuth
    from werkzeug.security import generate_password_hash, check_password_hash
    
    app = Flask(__name__)
    auth = HTTPBasicAuth()
    
    # 存储用户名和密码哈希值(密码是"hello")
    users = {
        "zhangsan": generate_password_hash("hello"),
        "lisi": generate_password_hash("bye")
    }
    
    @auth.verify_password
    def verify_password(username, password):
        """Flask-HTTPAuth 用于验证密码的回调函数"""
        if username in users and check_password_hash(users.get(username), password):
            return username  # 返回非None值表示验证成功
    
    @app.route('/')
    @auth.login_required  # 此装饰器保护该路由,要求登录
    def index():
        return f"Hello, {auth.current_user()}! You are logged in."
    
    if __name__ == '__main__':
        app.run(debug=True, port=8000)

    运行后,访问 http://localhost:8000就会要求认证。

2.3 方案三:增强安全性(存储密码哈希)

绝对不要用明文存储密码。应使用werkzeug库的generate_password_hashcheck_password_hash方法来处理。

python 复制代码
from werkzeug.security import generate_password_hash, check_password_hash

# 在服务器启动前,预先为密码生成哈希值(只需做一次)
# 将生成的哈希值替换代码中的明文密码
hashed_password_1 = generate_password_hash('my_secure_password_1')
hashed_password_2 = generate_password_hash('my_secure_password_2')
print(f"用户1的密码哈希: {hashed_password_1}")
print(f"用户2的密码哈希: {hashed_password_2}")

# 在代码中,存储哈希值而非明文
users = {
    "user1": hashed_password_1,
    "user2": hashed_password_2
}

def verify_password(username, password):
    if username in users:
        # 检查输入的密码是否与存储的哈希值匹配
        return check_password_hash(users[username], password)
    return False

3. 重要安全提醒

  • 务必使用HTTPS :Basic认证仅用Base64编码密码,相当于明文传输。在公网或生产环境使用,必须部署SSL/TLS证书(HTTPS),否则密码极易被窃听。

  • 强密码策略:为认证账户设置强密码。

  • 防火墙配置:确保服务器防火墙只开放必要的端口。

4. 总结

选择方案的建议:

  • 快速实现且安全 :直接使用方案二(Flask + flask_httpauth) ,并结合方案三(密码哈希)

  • 深入学习原理 :尝试方案一(标准库手动实现)

相关推荐
H Journey2 小时前
Linux sudo 命令完全指南
linux·运维·服务器·sudo
cuber膜拜2 小时前
Weaviate 简介与基本使用
数据库·python·docker·向量数据库·weaviate
开开心心_Every2 小时前
家常菜谱软件推荐:分类齐全无广告步骤详细
linux·运维·服务器·华为od·edge·pdf·华为云
i建模2 小时前
在 Arch Linux 中安装 **Xorg 服务器**
linux·运维·服务器
HealthScience2 小时前
DNA具体怎么转为蛋白质的?
python
PacosonSWJTU3 小时前
mac-python解释器理解与python安装
开发语言·python
Trouvaille ~3 小时前
【Linux】线程同步与互斥(一):线程互斥原理与mutex详解
linux·运维·服务器·c++·算法·线程·互斥锁
urkay-3 小时前
Android 中实现 HMAC-SHA256
android·开发语言·python
Fᴏʀ ʏ꯭ᴏ꯭ᴜ꯭.3 小时前
Keepalived 双主(Active‑Active)模式
运维·服务器