Python实现Web登录功能:从基础到安全实践
1. Python登录功能实现基础登录功能是绝大多数Web应用的基础模块对于Python初学者来说实现一个简单的登录系统是掌握Web开发的重要一步。这个看似简单的功能背后其实涉及了用户认证、会话管理、密码安全等多个关键知识点。1.1 登录功能的核心组件一个完整的登录系统通常包含以下几个核心部分用户输入界面用于收集用户名和密码验证逻辑核对用户凭证的正确性会话管理登录成功后维持用户状态安全防护防止暴力破解和注入攻击在Python中我们可以使用多种方式实现这些功能从最简单的控制台输入到完整的Web框架集成方案。1.2 基础实现方案选择对于初学者来说建议从最简单的实现方式开始控制台版本使用input()函数获取用户名和密码文件存储版本将用户信息存储在文本文件中数据库版本使用SQLite等轻量级数据库Web框架版本结合Flask/Django等框架实现我们先从最基础的控制台版本开始逐步深入。2. 控制台登录实现详解2.1 基础代码结构下面是一个最简单的控制台登录实现# 预定义的正确用户名和密码 CORRECT_USERNAME admin CORRECT_PASSWORD 123456 def login(): # 获取用户输入 username input(请输入用户名: ) password input(请输入密码: ) # 验证凭证 if username CORRECT_USERNAME and password CORRECT_PASSWORD: print(登录成功) else: print(用户名或密码错误) # 调用登录函数 login()这个实现虽然简单但包含了登录功能的核心逻辑获取输入、验证凭证、返回结果。2.2 代码优化与改进基础版本存在几个明显问题密码明文显示不安全只有一次尝试机会凭证硬编码在代码中改进后的版本import getpass # 用于安全获取密码 # 预定义的正确用户名和密码 CORRECT_CREDENTIALS { admin: 123456, user1: password1 } def secure_login(): max_attempts 3 attempts 0 while attempts max_attempts: username input(用户名: ) password getpass.getpass(密码: ) # 密码输入时不回显 if username in CORRECT_CREDENTIALS and CORRECT_CREDENTIALS[username] password: print(f欢迎回来{username}) return True attempts 1 remaining max_attempts - attempts if remaining 0: print(f认证失败还剩{remaining}次尝试机会) else: print(尝试次数过多登录失败) return False secure_login()3. 文件存储用户系统实现3.1 用户数据存储设计将用户信息存储在文件中是更实际的方案。我们可以使用JSON格式存储用户数据{ users: [ { username: admin, password: 5f4dcc3b5aa765d61d8327deb882cf99, # MD5加密后的password salt: abc123 } ] }3.2 密码安全处理明文存储密码是严重的安全隐患。我们需要对密码进行哈希处理import hashlib import json import os def hash_password(password, saltNone): 使用SHA256哈希密码 if salt is None: salt os.urandom(16).hex() # 生成随机盐值 return hashlib.sha256((password salt).encode()).hexdigest(), salt def create_user(username, password): 创建新用户 hashed_pw, salt hash_password(password) user { username: username, password: hashed_pw, salt: salt } return user def verify_user(stored_user, input_password): 验证用户密码 hashed_input, _ hash_password(input_password, stored_user[salt]) return hashed_input stored_user[password]3.3 完整文件登录系统实现import json class FileUserSystem: def __init__(self, filenameusers.json): self.filename filename self.users self._load_users() def _load_users(self): 从文件加载用户数据 try: with open(self.filename, r) as f: return json.load(f).get(users, []) except (FileNotFoundError, json.JSONDecodeError): return [] def _save_users(self): 保存用户数据到文件 with open(self.filename, w) as f: json.dump({users: self.users}, f, indent2) def add_user(self, username, password): 添加新用户 if any(u[username] username for u in self.users): return False new_user create_user(username, password) self.users.append(new_user) self._save_users() return True def authenticate(self, username, password): 验证用户登录 user next((u for u in self.users if u[username] username), None) if user and verify_user(user, password): return True return False # 使用示例 user_system FileUserSystem() user_system.add_user(admin, securepassword) if user_system.authenticate(admin, securepassword): print(登录成功) else: print(登录失败)4. Web框架登录实现Flask示例4.1 Flask基础登录实现对于Web应用我们可以使用Flask框架实现登录功能from flask import Flask, request, redirect, url_for, session, flash import hashlib app Flask(__name__) app.secret_key your_secret_key_here # 生产环境要用更安全的密钥 # 模拟用户数据库 users { admin: { password: 5f4dcc3b5aa765d61d8327deb882cf99, # password的MD5 name: Administrator } } app.route(/login, methods[GET, POST]) def login(): if request.method POST: username request.form[username] password hashlib.md5(request.form[password].encode()).hexdigest() if username in users and users[username][password] password: session[username] username flash(登录成功, success) return redirect(url_for(dashboard)) else: flash(用户名或密码错误, error) return form methodpost 用户名: input typetext nameusernamebr 密码: input typepassword namepasswordbr input typesubmit value登录 /form app.route(/dashboard) def dashboard(): if username not in session: return redirect(url_for(login)) return f欢迎, {users[session[username]][name]}! app.route(/logout) def logout(): session.pop(username, None) return redirect(url_for(login)) if __name__ __main__: app.run(debugTrue)4.2 安全增强措施基础Web登录需要添加以下安全措施使用更安全的哈希算法如bcrypt实现CSRF防护添加登录尝试限制使用HTTPS加密传输改进后的安全版本from flask import Flask, request, redirect, url_for, session, flash from flask_wtf.csrf import CSRFProtect import bcrypt from datetime import datetime, timedelta app Flask(__name__) app.secret_key your_very_secure_secret_key csrf CSRFProtect(app) # 用户数据库模拟 users { admin: { password: bcrypt.hashpw(bsecurepassword, bcrypt.gensalt()).decode(), name: Admin, failed_attempts: 0, last_attempt: None } } app.route(/login, methods[GET, POST]) def login(): if request.method POST: username request.form.get(username) password request.form.get(password) user users.get(username) # 检查账户是否被锁定 if user and user.get(locked_until) and user[locked_until] datetime.now(): remaining (user[locked_until] - datetime.now()).seconds // 60 flash(f账户已锁定请{remaining}分钟后再试, error) return redirect(url_for(login)) # 验证凭证 if user and bcrypt.checkpw(password.encode(), user[password].encode()): # 重置失败计数 user[failed_attempts] 0 session[username] username flash(登录成功, success) return redirect(url_for(dashboard)) else: # 记录失败尝试 if user: user[failed_attempts] 1 user[last_attempt] datetime.now() # 超过5次失败锁定账户30分钟 if user[failed_attempts] 5: user[locked_until] datetime.now() timedelta(minutes30) flash(由于多次登录失败账户已被临时锁定, error) else: flash(f用户名或密码错误还剩{5 - user[failed_attempts]}次尝试机会, error) else: flash(用户名或密码错误, error) return form methodpost input typehidden namecsrf_token value{{ csrf_token() }} 用户名: input typetext nameusername requiredbr 密码: input typepassword namepassword requiredbr input typesubmit value登录 /form # 其他路由保持不变...5. 常见问题与解决方案5.1 密码安全最佳实践永远不要明文存储密码使用专门的密码哈希函数如bcrypt、PBKDF2、Argon2为每个用户使用唯一的盐值设置适当的哈希计算成本参数# 使用bcrypt的推荐方式 import bcrypt # 生成哈希 password bsecurepassword hashed bcrypt.hashpw(password, bcrypt.gensalt(rounds12)) # rounds控制计算成本 # 验证密码 if bcrypt.checkpw(battemptedpassword, hashed): print(密码正确) else: print(密码错误)5.2 会话安全注意事项使用安全的会话cookie设置设置合理的会话过期时间实现会话固定保护敏感操作需要重新认证Flask中的安全会话配置示例app.config.update( SESSION_COOKIE_SECURETrue, # 仅HTTPS传输 SESSION_COOKIE_HTTPONLYTrue, # 防止JavaScript访问 SESSION_COOKIE_SAMESITELax, # CSRF防护 PERMANENT_SESSION_LIFETIMEtimedelta(hours2) # 会话有效期 )5.3 验证码集成为防止暴力破解可以添加验证码功能from flask import make_response import random import string from io import BytesIO from PIL import Image, ImageDraw, ImageFont import matplotlib.font_manager as fm app.route(/captcha) def captcha(): # 生成随机验证码 captcha_text .join(random.choices(string.ascii_uppercase string.digits, k4)) session[captcha] captcha_text # 创建验证码图片 font_path fm.findfont(fm.FontProperties(familyDejaVu Sans)) font ImageFont.truetype(font_path, 28) image Image.new(RGB, (120, 40), color(240, 240, 240)) draw ImageDraw.Draw(image) draw.text((10, 5), captcha_text, fontfont, fill(0, 0, 0)) # 添加干扰线 for _ in range(5): x1 random.randint(0, 120) y1 random.randint(0, 40) x2 random.randint(0, 120) y2 random.randint(0, 40) draw.line((x1, y1, x2, y2), fill(0, 0, 0), width1) # 返回图片响应 img_io BytesIO() image.save(img_io, PNG) img_io.seek(0) response make_response(img_io.getvalue()) response.headers[Content-Type] image/png return response然后在登录表单中添加验证码输入框img src/captcha alt验证码br input typetext namecaptcha placeholder输入验证码 required并在登录逻辑中添加验证码验证if session.get(captcha, ).lower() ! request.form.get(captcha, ).lower(): flash(验证码错误, error) return redirect(url_for(login))6. 进阶主题与扩展方向6.1 OAuth第三方登录集成现代应用常集成第三方登录如Google、Facebook等。以Flask-OAuthlib为例from flask_oauthlib.client import OAuth oauth OAuth(app) google oauth.remote_app( google, consumer_keyyour_google_client_id, consumer_secretyour_google_client_secret, request_token_params{ scope: email }, base_urlhttps://www.googleapis.com/oauth2/v1/, request_token_urlNone, access_token_methodPOST, access_token_urlhttps://accounts.google.com/o/oauth2/token, authorize_urlhttps://accounts.google.com/o/oauth2/auth, ) app.route(/login/google) def login_google(): return google.authorize(callbackurl_for(authorized_google, _externalTrue)) app.route(/login/google/callback) def authorized_google(): resp google.authorized_response() if resp is None: return Access denied: reason{} error{}.format( request.args[error_reason], request.args[error_description] ) session[google_token] (resp[access_token], ) user_info google.get(userinfo) return fLogged in as: {user_info.data[email]}6.2 JWT认证实现对于API服务JWT(JSON Web Token)是常用的认证方式import jwt from datetime import datetime, timedelta from functools import wraps from flask import request, jsonify app.config[SECRET_KEY] your_jwt_secret_key def generate_token(user_id): payload { sub: user_id, iat: datetime.utcnow(), exp: datetime.utcnow() timedelta(days1) } return jwt.encode(payload, app.config[SECRET_KEY], algorithmHS256) def token_required(f): wraps(f) def decorated(*args, **kwargs): token request.headers.get(Authorization) if not token: return jsonify({message: Token is missing}), 401 try: data jwt.decode(token.split()[1], app.config[SECRET_KEY], algorithms[HS256]) current_user data[sub] except: return jsonify({message: Token is invalid}), 401 return f(current_user, *args, **kwargs) return decorated app.route(/api/login, methods[POST]) def api_login(): auth request.authorization if not auth or not auth.username or not auth.password: return jsonify({message: Could not verify}), 401 # 验证用户逻辑... if valid_login(auth.username, auth.password): token generate_token(auth.username) return jsonify({token: token}) return jsonify({message: Invalid credentials}), 401 app.route(/api/protected) token_required def protected_route(current_user): return jsonify({message: fHello {current_user}})6.3 双因素认证(2FA)实现提升安全性可以添加双因素认证import pyotp import qrcode from io import BytesIO import base64 def generate_2fa_secret(user): 为用户生成2FA密钥 secret pyotp.random_base32() users[user][2fa_secret] secret return secret def get_2fa_uri(user, secret): 获取2FA设置二维码URI return pyotp.totp.TOTP(secret).provisioning_uri( nameuser, issuer_nameYour App Name ) def verify_2fa_code(user, code): 验证2FA代码 secret users[user].get(2fa_secret) if not secret: return False return pyotp.TOTP(secret).verify(code) # 在Flask路由中使用 app.route(/setup_2fa) def setup_2fa(): if username not in session: return redirect(url_for(login)) user session[username] secret generate_2fa_secret(user) uri get_2fa_uri(user, secret) # 生成二维码图片 img qrcode.make(uri) img_io BytesIO() img.save(img_io, PNG) img_io.seek(0) img_data base64.b64encode(img_io.getvalue()).decode() return f h2设置双因素认证/h2 p请使用认证APP扫描下方二维码:/p img srcdata:image/png;base64,{img_data} alt2FA QR Code p或手动输入密钥: {secret}/p form action/verify_2fa methodpost input typetext namecode placeholder输入6位验证码 input typesubmit value验证 /form app.route(/verify_2fa, methods[POST]) def verify_2fa(): if username not in session: return redirect(url_for(login)) user session[username] code request.form.get(code) if verify_2fa_code(user, code): session[2fa_verified] True return redirect(url_for(dashboard)) else: flash(验证码错误, error) return redirect(url_for(setup_2fa))

相关新闻

机器学习模型上线后的系统性风险与生产治理实践

机器学习模型上线后的系统性风险与生产治理实践

1. 为什么“模型上线”不是终点,而是系统性风险的起点你有没有经历过这样的场景:凌晨两点,手机突然震动,一条告警信息跳出来——“信用评分服务P99延迟突破800ms,超阈值300%”。你抓起电脑冲进工位,发现日志…

2026/10/13 14:09:03 阅读更多 →
Python编程入门:从基础语法到开发环境配置

Python编程入门:从基础语法到开发环境配置

1. Python语言概述 Python是一种高级、解释型、通用的编程语言,由Guido van Rossum于1991年首次发布。它以简洁明了的语法和强大的功能而闻名,特别适合初学者学习编程,同时也被广泛应用于科学计算、数据分析、人工智能、Web开发等专业领域。…

2026/10/9 15:17:00 阅读更多 →
千企进高校,校企面对面——黄河交通学院产教融合对接交流会开幕

千企进高校,校企面对面——黄河交通学院产教融合对接交流会开幕

7月16日上午,焦作市“千企进高校”系列活动——黄河交通学院产教融合对接交流会开幕式在黄河交通学院东校区一号学术报告厅举行。焦作市人力资源和社会保障局党组成员、副局长郑昌满出席,焦作市及各县(市、区)人社部门领导&#x…

2026/10/4 17:54:55 阅读更多 →

最新新闻

linux-dash 全局 CSS 层解析:main、plugins-container、tables 如何撑起一套极简监控面板样式

linux-dash 全局 CSS 层解析:main、plugins-container、tables 如何撑起一套极简监控面板样式

运维观测指标监控监控大盘 【免费下载链接】linux-dash A beautiful web dashboard for Linux 项目地址: https://gitcode.com/gh_mirrors/li/linux-dash 点击查看 免费下载 本文以 src/css/README.md 中描述的"全局基础样式文件"(Global CSS…

2026/10/14 2:23:24 阅读更多 →
10.5 GHz 相控阵雷达开源了:四块板与 10 层混压 PCB 拆解

10.5 GHz 相控阵雷达开源了:四块板与 10 层混压 PCB 拆解

10.5 GHz 相控阵雷达开源了:四块板与 10 层混压 PCB 拆解 【免费下载链接】PLFM_RADAR Open-source, low-cost 10.5 GHz PLFM phased array RADAR system 项目地址: https://gitcode.com/GitHub_Trending/pl/PLFM_RADAR 如果告诉你,一套 16 通道 …

2026/10/14 2:23:24 阅读更多 →
Matlab findpeaks峰值检测:参数调优与实战避坑指南

Matlab findpeaks峰值检测:参数调优与实战避坑指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 2:23:24 阅读更多 →
Java小白如何三天速通redis?

Java小白如何三天速通redis?

大家都知道Redis的业务范围是非常广的,但是对于刚入行的小伙伴来说可能也就知道个缓存跟分布式锁。因为Redis的很多功能在一些小企业里,根本是用不到的,得等到并发量到了一定的程度,系统扛不住了,才会用到Redis那些高级…

2026/10/14 2:23:24 阅读更多 →
Viper 回连过滤(Handler Firewall):按 IP 精准管控监听回连的实战指南

Viper 回连过滤(Handler Firewall):按 IP 精准管控监听回连的实战指南

文档教程网络安全 【免费下载链接】Viper Adversary simulation and Red teaming platform with AI 项目地址: https://gitcode.com/gh_mirrors/vip/Viper 点击查看 免费下载 Viper 的**回连过滤(Handler Firewall)**是内置在监听器&#xf…

2026/10/14 2:23:24 阅读更多 →
A*算法在路径规划中的原理与实践优化

A*算法在路径规划中的原理与实践优化

1. 路径规划中的A*算法初探第一次接触A算法是在开发仓库机器人导航系统时。当时我们尝试了Dijkstra、深度优先搜索等各种路径规划方法,要么计算时间太长,要么找到的路径不够优化。直到一位同事推荐了A算法,测试效果令人惊艳——在100x100的网…

2026/10/14 2:22:24 阅读更多 →

日新闻

AnyPS5通用适配层设计:兼容性与性能的工程取舍

AnyPS5通用适配层设计:兼容性与性能的工程取舍

1. 从"AnyPS5"这个名字说起:它到底想解决什么问题第一次看到"AnyPS5"这个标题,我脑子里冒出来的第一个念头是:这大概率是一个围绕"跨平台运行"或者"通用适配"做文章的项目。名字里的"Any"…

2026/10/14 0:00:41 阅读更多 →
Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

1. 项目概述:Flutter跨平台二手交易应用开发作为一名长期从事移动应用开发的工程师,我最近完成了一个基于Flutter框架的二手物品交易平台项目。这个项目最吸引我的地方在于它完美结合了Flutter的跨平台优势与HarmonyOS的生态特性,实现了"…

2026/10/14 0:00:41 阅读更多 →
DFS算法解决飞机降落调度问题实战

DFS算法解决飞机降落调度问题实战

1. 项目背景与核心思路飞机降落问题是一个经典的调度优化场景,也是算法竞赛和面试中的高频题目。这个题目要求我们合理安排多架飞机的降落顺序和时间,确保所有飞机都能安全着陆而不发生冲突。在实际航空管制中,这类问题直接关系到飞行安全和机…

2026/10/14 0:00:41 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/13 2:54:56 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/13 16:22:04 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/13 1:58:08 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 22:01:27 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 14:57:39 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 18:11:17 阅读更多 →