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
第二步:复制粘贴代码
第三步:测试运行
第四步: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,搞定,下班走人