如何使用 HTTP 摘要进行身份验证?

How do I authenticate with HTTP Digest?

我目前正在使用基本身份验证,遵循 this tutorial:

import secrets

from fastapi import FastAPI, Depends, HTTPException, status
from fastapi.security import HTTPBasic, HTTPBasicCredentials,

http_basic = HTTPBasic()

def authorize_basic(credentials: HTTPBasicCredentials = Depends(http_basic)):
    correct_username = secrets.compare_digest(credentials.username, "test")
    correct_password = secrets.compare_digest(credentials.password, "test")
    if not (correct_username and correct_password):
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Incorrect username or password",
            headers={"WWW-Authenticate": "Basic"},
        )

@app.get("/auth/", dependencies=[Depends(authorize_basic)])
def auth():
    return {"success": "true"}

如何改用 HTTPDigest?

我知道很久以前就有人问过这个问题,但是 FastAPI 测试套件中的这个 example 展示了如何做。

你可以将上面的例子重写如下:

import base64
import secrets

from fastapi import Depends, FastAPI, HTTPException, Security, status
from fastapi.security import HTTPAuthorizationCredentials, HTTPDigest

http_digest = HTTPDigest()

app = FastAPI()


def authorize_digest(credentials: HTTPAuthorizationCredentials = Security(http_digest)):
    # Credentials returns the token as string.
    incoming_token = credentials.credentials

    # Let's say you want to generate the digest token from username and pass.
    expected_username = "test"
    expected_password = "test"

    # Digest tokens are encoded via base64 encoding algo.
    expected_token = base64.standard_b64encode(
        bytes(f"{expected_username}:{expected_password}", encoding="UTF-8"),
    )

    correct_token = secrets.compare_digest(
        bytes(incoming_token, encoding="UTF-8"),
        expected_token,
    )
    if not correct_token:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Incorrect digest token",
            headers={"WWW-Authenticate": "Digest"},
        )


@app.get("/auth/", dependencies=[Depends(authorize_digest)])
def auth():
    return {"success": "true"}

您可以使用您的 shell 中的用户名和密码获取令牌(假设您使用的是 Unix-y 系统):

python -c 'import base64; h = base64.urlsafe_b64encode(b"test:test"); print(h)'

这假设您的用户名和密码都是 test。它将打印以下内容:

b'dGVzdDp0ZXN0'

您可以使用此令牌并通过 curl 向此 API 发送请求:

curl -X 'GET' 'http://localhost:5000/auth/' \
        -H 'accept: application/json' \
        -H "Authorization: Digest dGVzdDp0ZXN0" \
        -H 'Content-Type: application/json' \

这将打印出成功响应:

{"success":"true"}