为了账号安全,请及时绑定邮箱和手机立即绑定

如何用Clerk和FastAPI验证API请求的Token身份

标签:
Python 安全 API

利用FastAPI内置的HTTPBearer工具来验证bearer令牌的有效性,并在Python API应用程序中获取有效的用户会话

需要对你的Python API调用进行验证但找不到相关教程或SDK吗?这几个简单的步骤就能搞定!

使用Clerk和FastAPI进行认证和Bearer令牌验证

在构建SaaS时,我发现Clerk目前还没有提供Python SDK(可能还没有?),所以我决定深入研究一下看看有没有办法使用FastAPI内置的安全工具(FastAPI安全工具)来读取和验证从我的前端应用发送的承载令牌认证信息。

快速开始,只需按照以下步骤。

A. 准备工作如下

如果你已经有一个 FastAPI 应用程序,可以直接跳过这些内容。

1. 安装依赖项.

使用pip将这些包添加到你的Python项目中:

    # 创建虚拟环境  
    python -m venv venv  

    # 激活虚拟环境(venv)  
    source venv/bin/activate  

    # 安装依赖  
    pip install fastapi uvicorn
2. 查看 HTTP 请求的内容

server.py 文件中创建一个监听 8000 端口的服务器,比如:

    从 fastapi 导入 FastAPI 作为 app  

    app = FastAPI()  

    @app.get("/")  
    async def root():  
        return {"message": "Hello World"}  

    如果 __name__ == "__main__":  
        导入 uvicorn  
        uvicorn.run(app, host="0.0.0.0", port=8000)

我喜欢用这种方法来运行 uvicorn,这样就不需要单独安装 uvicorn 的命令行工具,而是直接运行 python server.py 即可。试试看:可以尝试在命令行中输入 python server.py 来启动服务器。

    python server.py  

    启动服务器进程 [54863] 成功。  
    等待应用启动。  
    应用启动完成。  
    Uvicorn 正在 http://0.0.0.0:8000 上运行中(按 CTRL+C 可停止程序)。
验证Bearer Token
1. 解析携带令牌。

我们将使用FastAPI HTTPBearer实用程序从Authorization HTTP头读取令牌。

当然我们也可以直接通过字符串操作从头部解析出这个token,不过使用这个工具能让代码更易读。代码整洁就更好了。

server.py 文件中加入以下代码行(如下注释 1 至 6)。

    from fastapi import FastAPI, Depends # <- (1)  # 导入相关模块
    from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer # <- (2)  # 导入相关模块
    from typing import Annotated # <- (3)  

    app = FastAPI()  
    security = HTTPBearer() # <- (4)  security = HTTPBearer()

    @app.get("/")  
    async def root(  
        credentials: Annotated[HTTPAuthorizationCredentials, Depends(security)] # <- (5)  凭证: Annotated[HTTPAuthorizationCredentials, Depends(security)]
    ):  
        print(f"收到的token: {credentials.credentials[:10]}...") # <- (6)  
        return {"message": "Hello World"}  

    if __name__ == "__main__":  
        import uvicorn  
        uvicorn.run(app, host="0.0.0.0", port=8000)

让我们启动服务器,然后做一些测试。

    python server.py  
    INFO:     服务器进程 [55315] 已启动运行  
    INFO:     正在等待应用启动。  
    INFO:     应用启动完成。  
    INFO:     Uvicorn 正在 http://0.0.0.0:8000 上运行中(按 Ctrl+C 即可停止)

从另一个终端输入。

    # 发送一个没有认证令牌的请求  
    curl -i localhost:8000  
    HTTP/1.1 403 Forbidden  
    日期: 2024年2月17日 09:51:19 GMT  
    服务器: uvicorn  
    内容大小: 30  
    内容类型: application/json  

    {"detail":"未认证"}  

    # 现在我发送一个(随便的)认证令牌  
    curl -i localhost:8000 -H 'Authorization: Bearer 超级秘密'  
    HTTP/1.1 200 OK  
    日期: 2024年2月17日 09:52:41 GMT  
    服务器: uvicorn  
    内容大小: 25  
    内容类型: application/json  

    {"message":"Hello World"}  

    # ... 并且我可以看到我的服务器打印以下内容:  
    获取令牌: supersecre...  
    INFO: 127.0.0.1:50722 - "GET / HTTP/1.1" 200 OK
2. 验证 token.

使用离线验证,我们可以使用我们的JWT签名密钥来验证令牌的有效性,其中“JWT”代表“JSON Web Token”。

安装如下所示包含 cryptography 包的 PyJWT 库。

pip install "pyjwt[crypto]" # 安装 pyjwt 包及其 crypto 扩展

server.py 文件中,添加或修改以下几行。

    import requests # <- (1)  
    from fastapi import FastAPI, Depends, Response, status # <- (2)  
    from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer  
    from typing import Annotated  

    CLERK_PEM_PUBLIC_KEY = """  
    -----BEGIN PUBLIC KEY-----  
    <YOUR JWT PUBLIC KEY>  
    -----END PUBLIC KEY-----  
    """ # <- (3)  

    app = FastAPI()  
    security = HTTPBearer()  

    @app.get("/")  
    async def root(  
        credentials: Annotated[HTTPAuthorizationCredentials, Depends(security)],  
        response: Response # <- (4)  
    ):  
        print(f"收到的令牌是: {credentials.credentials[:10]}...")  

        # (5) 添加以下部分  
        try:  
            jwt.decode(token, key=CLERK_PEM_PUBLIC_KEY, algorithms=['RS256'])  
            return {"message": "Hello World"}  
        except jwt.exceptions.PyJWTError:  
            response.status_code = status.HTTP_400_BAD_REQUEST  
            return {"message": "无效的令牌"}  

    if __name__ == "__main__":  
        import uvicorn  
        uvicorn.run(app, host="0.0.0.0", port=8000)

要测试这一点,我们可以在控制台中运行以下代码:await Clerk.session.getToken(),从而找到前端应用在登录时使用的 token。

从终端运行以下:

    # 没有有效的token  
    curl -i localhost:8000 -H 'Authorization: Bearer invalidtoken'  
    HTTP/1.1 400 Bad Request  
    date: Sun, 18 Feb 2024 13:21:01 GMT  
    server: uvicorn  
    content-length: 27  
    content-type: application/json  

    {"message":"无效的Token"}  

    # 有有效的token  
    curl -i localhost:8000 -H 'Authorization: Bearer eyJhbGc...'  
    HTTP/1.1 200 OK  
    date: Sun, 18 Feb 2024 13:08:58 GMT  
    server: uvicorn  
    content-length: 25  
    content-type: application/json  

    {"message":"Hello World"}

而且它有效了🎉!应用程序确实检查token是否有效且尚未过期。

这些资源

想联系我吗?我还在以下社交平台上也很活跃:

Twitter: https://twitter.com/redouaneoachour

领英:https://www.linkedin.com/in/redouane-achouri/

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消