fastapi设置登录限制
需求:
- 使用fastapi搭建一个站点
- 使用MySQL存储用户名和密码,用户名为明文,密码为密文
- 用户首页需要用户登录之后才能访问,如果未登录访问首页则跳转登录页面
一,使用fastapi搭建一个无需验证的首页
目录结构如下
其中主程序main.py
文件夹views下为html文件
main.py内容如下
from fastapi import FastAPI
from starlette.requests import Request
import uvicorn
import asyncio
from fastapi.responses import RedirectResponse, FileResponse
from fastapi.staticfiles import StaticFiles
import hashlib
import pymysql
app = FastAPI()
# 定义跟路由,访问跟则访问views目录下的index.html
@app.get("/")
async def index(request: Request):
return RedirectResponse(url="/index.html")
app.mount("/",StaticFiles(directory="views"),name='static')
if __name__ == '__main__':
uvicorn.run(app,host='0.0.0.0', port=8000, log_level='info', loop='asyncio')
启动
python main.py
页面访问返回Hello world字符串
二,增加验证功能
用户需要首页访问登录页面login输入正确的用户名和密码才能访问index.html首页
修改代码main.py
from fastapi import FastAPI,Form
from starlette.requests import Request
import uvicorn
import asyncio
from fastapi.responses import RedirectResponse, FileResponse
from fastapi.staticfiles import StaticFiles
import hashlib
import pymysql
app = FastAPI()
@app.get("/login")
async def login():
return RedirectResponse(url="/login.html")
@app.post("/login")
async def login(request: Request, username: str = Form(...), password: str = Form(...)):
print(username,password)
if username == "admin" and password == "passwd":
return FileResponse('views/index.html')
else:
return FileResponse("views/login.html")
# 定义跟路由,访问跟则访问views目录下的index.html
@app.get("/")
async def index(request: Request):
return RedirectResponse("/login")
app.mount("/",StaticFiles(directory="views"),name='static')
if __name__ == '__main__':
uvicorn.run(app,host='0.0.0.0', port=8000, log_level='info', loop='asyncio')
修改代码解析
启动打开页面为登录页面输入正确的用户名和密码跳转index.html
以上代码存在的问题
- 模拟明文用户名和密码,没有加密存储到MySQL进行验证
- 虽然数对了模拟的用户名和密码可以正常跳转首页但是,但是直接输入首页地址也可以正常访问,未做到限制
三,修改代码使用MySQL存储用户名和密码进行验证
MySQL存储用户名使用明文,密码为密文
首先创建一个MySQL数据库并建表,表有两个字段username和password
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`username` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`password` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES ('test', '9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08');
INSERT INTO `user` VALUES ('admin', '0d6be69b264717f2dd33652e212b173104b4a647b7c11ae72e9885f11cd312fb');
SET FOREIGN_KEY_CHECKS = 1;
加密的pyhon代码如下
import hashlib
def sha256Encrypt(data):
# 将字符串编码为UTF-8格式,并转换为bytes类型
data = data.encode("utf-8")
# 创建SHA256对象
sha256 = hashlib.sha256()
# 更新SHA256对象的内容
sha256.update(data)
# 获取SHA256对象的摘要信息,返回一个bytes类型的字符串
digest = sha256.digest()
# 将bytes类型的字符串转换为十六进制字符串
encryptedData = digest.hex()
return encryptedData
print(sha256Encrypt('passwd'))
修改后代码如下
main.py
from fastapi import FastAPI,Form
from starlette.requests import Request
import uvicorn
import asyncio
from fastapi.responses import RedirectResponse, FileResponse
from fastapi.staticfiles import StaticFiles
import hashlib
import pymysql
app = FastAPI()
host = 'localhost'
user = 'root'
port = 3306
db = 'user'
password = 'Paic34#$'
def sha256Encrypt(data):
# 将字符串编码为UTF-8格式,并转换为bytes类型
data = data.encode("utf-8")
# 创建SHA256对象
sha256 = hashlib.sha256()
# 更新SHA256对象的内容
sha256.update(data)
# 获取SHA256对象的摘要信息,返回一个bytes类型的字符串
digest = sha256.digest()
# 将bytes类型的字符串转换为十六进制字符串
encryptedData = digest.hex()
return encryptedData
def get_user(username):
conn = get_connection()
# 使用 cursor() 方法创建一个 dict 格式的游标对象 cursor
cursor = conn.cursor(pymysql.cursors.DictCursor)
# 使用 execute() 方法执行 SQL 查询
cursor.execute("SELECT username,password FROM user WHERE username = %s limit 1", username)
# 使用 fetchone() 方法获取单条数据.
# 返回为一个根据用户名查询到的字典{'username': 'test', 'password': '9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08'}
data = cursor.fetchone()
# 关闭数据库连接
cursor.close()
conn.close()
print('get_user返回',data)
return data
# ---- 用pymysql 操作数据库
def get_connection():
conn = pymysql.connect(host=host, port=port, db=db, user=user, password=password)
return conn
@app.get("/login")
async def login():
return RedirectResponse(url="/login.html")
@app.post("/login")
async def login(request: Request, username: str = Form(...), password: str = Form(...)):
print(username,password)
# 如果用户名和密码不为空则使用用户名去数据库查询,返回字典{'username': 'test', 'password': '9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08'}
if username and password:
user = get_user(username)
if user and len(user) > 0 and sha256Encrypt(password) == user['password']:
print('sucess')
return FileResponse('views/index.html')
return FileResponse('views/login.html')
# 定义跟路由,访问跟则访问views目录下的index.html
@app.get("/")
async def index(request: Request):
return RedirectResponse("/login")
app.mount("/",StaticFiles(directory="views"),name='static')
if __name__ == '__main__':
uvicorn.run(app,host='0.0.0.0', port=8000, log_level='info', loop='asyncio')
启动访问,输入错误的用户名和密码则不会跳转,输入正确的用户名密码admin passwd则跳转
以上代码存在的问题是还是没有对index.html进行限制直接输入页面还是可以访问
四,修改代码添加session进行限制
分类:
Python学习
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
2021-07-22 VS code设置Python调试模式
2020-07-22 第六讲:prometheus初探和配置
2020-07-22 第五讲:prometheus监控数据格式学习
2019-07-22 Python3之内建模块itertools