问题
我正在开发一个FastAPI应用程序,它需要对用户到达的某些端点进行身份验证。我正在使用Oauth2和FastAPI中的Jose创建用于身份验证过程的JWT。在进行了一些研究之后,确保令牌在前端受到保护的最佳方法似乎是将它们存储在HttpOnly Cookies中。我很难理解如何通过HttpOnly Cookies正确地传递JWT,以便我的FastAPI服务器能够在头中验证JWT。目前,当我尝试将JWT令牌作为HttpOnly Cookie传递时,我会得到一个401 Unauthorized Error
。
我试过的
当我将令牌作为模板字符串编码到标头中时,我已经能够使用JWT令牌成功地验证用户的身份。但是,当我将JWT作为Cookie通过头传递给FastAPI服务器时,我的FastAPI服务器无法对用户进行身份验证并返回401 unauthorized error
。我试着查看网络选项卡,看看我向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: access_token="Bearer“
我还尝试更改了在服务器上设置cookie的方式,使标题看起来如下:
Cookie: Authentication="Bearer“
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);
}
FastAPI码
下面是保护我的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
下面是一个受保护端点的示例,它依赖于上面列出的get_current_user文件中的oauth2函数。
@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"}
我似乎遇到了这个问题,因为我的get_current_user函数在Oauth2中只有在以以下格式从标题中获取JWT:
身份验证:承载令牌
当令牌以下列任何一种格式存在时,它似乎无法从标头中验证令牌:
曲奇:access_token=“比勒令牌”Cookie: Authentication="Bearer令牌“
当我通过HttpOnly Cookies发送标头时,我是否需要以某种方式改变它们的发送方式,还是需要更改get_current_user函数的一些内容,从而使它能够正确地读取cookie头。
任何建议都是非常感谢的,并感谢您抽出时间阅读!
发布于 2022-12-01 06:57:41
要从cookie中获取令牌,而不是Authorization
头( OAuth2PasswordBearer的缺省值),告诉FastAPI,您希望令牌来自cookie而不是。
def get_current_user(access_token: str = Cookie(...), db: Session = Depends(database.get_db)):
这假设令牌被命名为access_token
(而不仅仅是令牌)。根据需要调整名称。
https://stackoverflow.com/questions/74634957
复制相似问题