fastapi设置登录限制

需求:

  1. 使用fastapi搭建一个站点
  2. 使用MySQL存储用户名和密码,用户名为明文,密码为密文
  3. 用户首页需要用户登录之后才能访问,如果未登录访问首页则跳转登录页面

一,使用fastapi搭建一个无需验证的首页

目录结构如下
image
其中主程序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字符串
image

二,增加验证功能

用户需要首页访问登录页面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')

修改代码解析
image
启动打开页面为登录页面输入正确的用户名和密码跳转index.html
以上代码存在的问题

  1. 模拟明文用户名和密码,没有加密存储到MySQL进行验证
  2. 虽然数对了模拟的用户名和密码可以正常跳转首页但是,但是直接输入首页地址也可以正常访问,未做到限制

三,修改代码使用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进行限制

posted @ 2023-07-22 16:50  minseo  阅读(216)  评论(0编辑  收藏  举报