fastapi学习记录【四】

代码地址:GitHub - wendingming/fastapi-vue-postgresql: fastapi+vue+postgresql搭建项目fastapi+vue+postgresql搭建项目. Contribute to wendingming/fastapi-vue-postgresql development by creating an account on GitHub.https://github.com/wendingming/fastapi-vue-postgresql

fastapi使用uvicorn启动,更改默认端口。

参考一下文章:

uvicorn 更改fastapi 运行host和port_solocao的专栏-CSDN博客

之前是运行uvicorn main:app --reload启动,

默认的端口是8000,因为有很多项目,有些以前的项目也是使用8000端口,所以想改改,于是找到上面的博文,启动代码改成:

uvicorn main:app --host '0.0.0.0' --port 9000 --reload

然后在pycharm,Terminal输入新的启动代码,重新启动。

经过我的反复尝试,以下代码才能启动成功。否则报错。

uvicorn main:app --reload --port 9000

我也不知道什么原理,解决就行。

如下图:

 接下来,准备更进一步加深学习。

首先是登录

目前流行的,登录后获取token,然后每次访问接口,都要带token,

所以准备先做登录接口,成功则返回登录结果和token值,失败则返回失败消息。

说干就干。

根据官方文档:使用(哈希)密码和 JWT Bearer 令牌的 OAuth2

使用(哈希)密码和 JWT Bearer 令牌的 OAuth2 - FastAPIhttps://fastapi.tiangolo.com/zh/tutorial/security/oauth2-jwt/第一步:引用相关库       

第二步:复制粘贴代码

第三步:测试运行

第四步:apipost测试访问接口

第五步:VUE前端测试登录

        第一步就遇到麻烦了,先是使用:

pip install python-jose[cryptography]
pip install passlib[bcrypt]

来安装库,结果超时错误,然后使用

pip install -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com python-jose[cryptography]

pip install -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com passlib[bcrypt]

指向国内数据源,结果提示版本不对,这个数据源也太落后了吧,不更新版本的,我所使用的python是3.7.7版本的。

没奈何,老老实实等吧,重新再用

pip install python-jose[cryptography]
pip install passlib[bcrypt]

等待下载完,超时就重新再次执行,还好,它如果下载过,再次下载的时候,已经下载的就跳过了。

然后等啊等的,总算安装完了,唉,下次搞个蕃蔷软件吧,今天浪费好多时间。

第二步,从官方文档复制代码,新建一个login.py,粘贴到这个文件中。

官网代码如下:

from datetime import datetime, timedelta
from typing import Optional

from fastapi import Depends, FastAPI, HTTPException, status
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
from jose import JWTError, jwt
from passlib.context import CryptContext
from pydantic import BaseModel

# to get a string like this run:
# openssl rand -hex 32
SECRET_KEY = "09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7"
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30


fake_users_db = {
    "johndoe": {
        "username": "johndoe",
        "full_name": "John Doe",
        "email": "johndoe@example.com",
        "hashed_password": "$2b$12$EixZaYVK1fsbw1ZfbX3OXePaWxn96p36WQoeG6Lruj3vjPGga31lW",
        "disabled": False,
    }
}


class Token(BaseModel):
    access_token: str
    token_type: str


class TokenData(BaseModel):
    username: Optional[str] = None


class User(BaseModel):
    username: str
    email: Optional[str] = None
    full_name: Optional[str] = None
    disabled: Optional[bool] = None


class UserInDB(User):
    hashed_password: str


pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")

oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")

app = FastAPI()


def verify_password(plain_password, hashed_password):
    return pwd_context.verify(plain_password, hashed_password)


def get_password_hash(password):
    return pwd_context.hash(password)


def get_user(db, username: str):
    if username in db:
        user_dict = db[username]
        return UserInDB(**user_dict)


def authenticate_user(fake_db, username: str, password: str):
    user = get_user(fake_db, username)
    if not user:
        return False
    if not verify_password(password, user.hashed_password):
        return False
    return user


def create_access_token(data: dict, expires_delta: Optional[timedelta] = None):
    to_encode = data.copy()
    if expires_delta:
        expire = datetime.utcnow() + expires_delta
    else:
        expire = datetime.utcnow() + timedelta(minutes=15)
    to_encode.update({"exp": expire})
    encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
    return encoded_jwt


async def get_current_user(token: str = Depends(oauth2_scheme)):
    credentials_exception = HTTPException(
        status_code=status.HTTP_401_UNAUTHORIZED,
        detail="Could not validate credentials",
        headers={"WWW-Authenticate": "Bearer"},
    )
    try:
        payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
        username: str = payload.get("sub")
        if username is None:
            raise credentials_exception
        token_data = TokenData(username=username)
    except JWTError:
        raise credentials_exception
    user = get_user(fake_users_db, username=token_data.username)
    if user is None:
        raise credentials_exception
    return user


async def get_current_active_user(current_user: User = Depends(get_current_user)):
    if current_user.disabled:
        raise HTTPException(status_code=400, detail="Inactive user")
    return current_user


@app.post("/token", response_model=Token)
async def login_for_access_token(form_data: OAuth2PasswordRequestForm = Depends()):
    user = authenticate_user(fake_users_db, form_data.username, form_data.password)
    if not user:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Incorrect username or password",
            headers={"WWW-Authenticate": "Bearer"},
        )
    access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
    access_token = create_access_token(
        data={"sub": user.username}, expires_delta=access_token_expires
    )
    return {"access_token": access_token, "token_type": "bearer"}


@app.get("/users/me/", response_model=User)
async def read_users_me(current_user: User = Depends(get_current_active_user)):
    return current_user


@app.get("/users/me/items/")
async def read_own_items(current_user: User = Depends(get_current_active_user)):
    return [{"item_id": "Foo", "owner": current_user.username}]

启动项目

uvicorn login:app --reload --port 9000

使用apipost工具,访问接口,如下图:

 嗯,复制粘贴就是爽,很快搞定。

第五步,使用VUE前端访问【暂缓,先把main.py引用login.py搞好】,这样就可以在main.py新建接口,把接口都放在一个文件里面,然后就花了很长时间,仔细研究代码,

A、main.py

        先引用:from login.py import 【token对应的方法】

        新增接口:login接口,直接调用login.py的【token对应的方法】

B、login.py

        修改token接口,改成方法,这样就可以在main.py调用了

修改后的main.py增加的代码如下:

from login import login_for_access_token,FormData

"""
main.py代码略,参考我之前的文章
"""

#新增接口login
@app.post("/login")
async def login_back_token(form_data: FormData):
    # 调用login.py的login_for_access_token方法
    token = login_for_access_token(form_data)
    return token

修改后的login.py修改的代码如下:


#-----新增部分star--------------------
class FormData(BaseModel):
    uname: str
    passwd: str

#-----修改部分star--------------------
# @app.post("/token", response_model=Token)<----------原本的代码
# async def login_for_access_token(form_data: FormData):<--------------原本的代码
def login_for_access_token(form_data: FormData):
    """这里定义了一个接口,路径为 /token, 用于用户申请tokens
    :param form_data:
    :return:
    """
    # 首先对用户做出检查
    user = authenticate_user(fake_users_db, form_data.uname, form_data.passwd)
    if not user:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Incorrect username or password",
            headers={"WWW-Authenticate": "Bearer"},
        )
    # 定义tokens过期时间
    access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
    # 创建token
    access_token = create_access_token(
        data={"sub": user.username}, expires_delta=access_token_expires
    )
    # 返回token信息,JavaScript接收并存储,用于下次访问
    baktoken = {
        "access_token": access_token, "token_type": "bearer"
    }
    #return {"access_token": access_token, "token_type": "bearer"}<----原来
    return baktoken
#-----修改部分end--------------------

OK,修改完毕,重启

uvicorn main:app --reload --port 9000

apipost重新访问接口

 OK,搞定,下班走人

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值