问题
我正在开发一个FastAPI应用程序,该应用程序要求对用户访问的某些端点进行身份验证,我正在使用FastAPI的Oauth2和Jose为身份验证过程创建JWT,看来确保令牌在前端受到保护的最好方法是将它们存储在HttpOnly Cookie中。我一直在努力理解如何正确地通过HttpOnly Cookie传递JWT,以便FastAPI服务器能够验证头中的JWT。目前,当我尝试将JWT标记作为HttpOnly Cookie传递时,我得到一个401 Unauthorized Error
。
我尝试过的
当我将JWT标记作为模板字符串编码到头中时,我已经能够成功地使用该标记对用户进行身份验证,但是,当我将JWT作为Cookie通过头传递给FastAPI服务器时,我的FastAPI服务器无法对用户进行身份验证,并返回401 unauthorized error
. I'为了更好地理解这两个场景之间的不同之处,我尝试查看了网络选项卡,以查看在我的请求中发送到FastApi服务器的报头是什么。
代码成功示例
当我将JWT作为模板字符串传递并得到200响应时,这是在标头中:
身份验证:承载令牌
async function getPosts() {
const url = "http://localhost:8000/posts";
const fetchConfig = {
headers: {
Authorization: `Bearer ${tokenValue}`,
},
};
const response = await fetch(url, fetchConfig);
const posts = await response.json();
}
不成功的代码示例
当我将JWT作为HttpOnly Cookie传递并获得401响应时,这是在标头中:
Cookie:访问令牌=“不记名令牌”
我也尝试过改变我在服务器上设置cookie的方式,使头看起来像这样:
Cookie:身份验证=“不记名令牌”
async function getPosts() {
const url = "http://localhost:8000/posts";
const fetchConfig = {
credentials: "include",
};
const response = await fetch(url, fetchConfig);
const posts = await response.json();
console.log(posts);
}
快速API代码
下面是保护API端点的Oauth2令牌验证的代码,它基于FastAPI文档中的示例:FastApi Oauth2
oauth2_scheme = OAuth2PasswordBearer(tokenUrl='login')
SECRET_KEY = settings.SECRET_KEY
ALGORITHM = settings.ALGORITHM
ACCESS_TOKEN_EXPIRE_MINUTES = settings.ACCESS_TOKEN_EXPIRE_MINUTES
def verify_access_token(token: str, credentials_exception):
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
id: str = payload.get("user_id")
if id is None:
raise credentials_exception
token_data = schemas.TokenData(id=id)
except JWTError:
raise credentials_exception
return token_data
def get_current_user(token: str = Depends(oauth2_scheme), db: Session = Depends(database.get_db)):
credentials_exception = HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail=f"Could not validate credentials",
headers={"WWW-Authenticate": "Bearer"}
)
token = verify_access_token(token, credentials_exception)
user = db.query(models.User).filter(models.User.id == token.id).first()
return user
下面是一个受保护端点的示例,它依赖于上面列出的oauth2文件中的get_current_user函数。
@router.get("/", response_model=List[schemas.PostOut])
def get_posts(db: Session = Depends(get_db), current_user: int = Depends(oauth2.get_current_user):
return {"Message": "Protected Endpoint Reached"}
看起来我遇到了这个问题,因为Oauth2中的get_current_user函数只能在JWT为以下格式时从头中获取JWT:
身份验证:承载令牌
当令牌为以下格式之一时,似乎无法从标头验证令牌:
Cookie:访问令牌=“不记名令牌”
Cookie:身份验证=“不记名令牌”
当我通过HttpOnly Cookie发送标头时,我是否需要以某种方式更改发送标头的方式,或者我是否需要更改get_current_user函数的某些内容,使其能够正确读取Cookie标头。
任何建议都非常感谢,感谢您抽出时间阅读本文!
1条答案
按热度按时间ctzwtxfj1#
若要从Cookie而不是
Authorization
信头(OAuth2PasswordBearer的预设值)取得Token,请使用tell FastAPI that you want the token to originate from a cookie instead。这假定标记已命名为
access_token
(而不仅仅是标记)。根据需要调整名称。