zoukankan      html  css  js  c++  java
  • FastAPI安全系列(一) OAuth2 .0认证基础

    一、介绍

    OAuth2 .0模式有四种分别是:

    • 授权码授权模式(Authorization Code Grant)
    • 隐式授权模式(Implicit Grant)
    • 密码授权模式(Resource Owner Password Credential Grant)
    • 客户端凭证授权模式(Client Credentials Grant)

    这里探讨的是第三种模式密码授权模式(Resource Owner Password Credential Grant),这种模式的流程:

    FastAPI中使用OAuth2来看一下它是如何使用工作的,然后来理解发生了什么。

    from fastapi import Depends, FastAPI
    from fastapi.security import OAuth2PasswordBearer
    
    app = FastAPI()
    
    oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
    
    
    @app.get("/items/")
    async def read_items(token: str = Depends(oauth2_scheme)):
        return {"token": token}

    访问 http://127.0.0.1:8000/docs#/

     在路径操作的右上角有一个可以点击的锁,如果你点击它,你会得到一个由username和password(以及其它的可选字段)的认证的表单。

    现在理解一下这个流程:

    • 在前端输入用户的username和password
    • 前台将用username和password发送给后台一个特殊API的URL(通过tokenUrl="token"声明的)
    • 这个特殊的API检查username和password,然后返回一个“token”,在下次请求时将会通过这个token进行用户验证,正常的是这个token是有过期时间的
    • 这个token前端会临时存储在某个地方
    • 然后每次请求时会携带一个Authorization的请求头
    • 后台会检查Authorization请求头中是否有token值,如果没有,直接返回401状态码以及UNAUTHORIZED错误信息

    FastAPI在不同的抽象级别提供了几个工具,用来实现这些安全特性。

     二、OAuth2PasswordBearer

    1、参数说明

     当我们通过OAuth2PasswordBearer类来创建一个实例,并且通过tokenUrl参数传递一个URL,客户端将会将username和password传递到这个URL对应的路径操作函数中,然后得到一个token。

    ...
    oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
    ...

    此处的tokenUrl="token"是相对路径,相当于tokenUrl="./token"。

    oauth2_schemes实例变量是可调用的,这就意味着它可以作为依赖项。所以在路径操作函数中:

    ...
    @app.get("/items/")
    async def read_items(token: str = Depends(oauth2_scheme)):
        return {"token": token}
    ...

      这个依赖项提供一个str用来标记路径操作函数的token参数。FastAPI知道它可以使用这个依赖在OpenAPI中来定义一个“安全模式”(以及自动交互的API文档)。

     2、获取当前用户

    上述基于安全系统向路径操作函数提供了一个str类型的token,但这并不是很实用,实际上可以使它返回当前的用户信息。

    •  创建用户模型
    from typing import Optional
    from pydantic import BaseModel
    
    class User(BaseModel):
        username: str
        email: Optional[str] = None
        full_name: Optional[str] = None
        disabled: Optional[bool] = None
    • 创建get_current_user依赖项

    此时可以将oauth2_scheme 作为get_current_user的依赖项,然后将get_current_user作为路径操作函数的依赖项。

    ...
    async def get_current_user(token: str = Depends(oauth2_scheme)):
        pass
    
    
    @app.get("/users/me")
    async def read_users_me(current_user: User = Depends(get_current_user)):
        return current_user
    ...
    • 获取用户
    ...
    def fake_decode_token(token):
        return User(
            username=token + "fakedecoded", email="john@example.com", full_name="John Doe"
        )
    
    
    async def get_current_user(token: str = Depends(oauth2_scheme)):
        user = fake_decode_token(token)
        return user
    ...
    • 注入当前用户
    ...
    @app.get("/users/me")
    async def read_users_me(current_user: User = Depends(get_current_user)):
        return current_user
    ...

    3、完整代码

    from typing import Optional
    from fastapi import Depends, FastAPI
    from fastapi.security import OAuth2PasswordBearer
    from pydantic import BaseModel
    
    app = FastAPI()
    
    oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
    
    
    class User(BaseModel):
        username: str
        email: Optional[str] = None
        full_name: Optional[str] = None
        disabled: Optional[bool] = None
    
    
    def fake_decode_token(token):
        return User(
            username=token + "fakedecoded", email="john@example.com", full_name="John Doe"
        )
    
    
    async def get_current_user(token: str = Depends(oauth2_scheme)):
        user = fake_decode_token(token)
        return user
    
    
    @app.get("/users/me")
    async def read_users_me(current_user: User = Depends(get_current_user)):
        return current_user
    作者:iveBoy
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须在文章页面给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    关于Java常见的误解
    Java程序设计概述
    是结束,更是开始!
    从零开始单排学设计模式「简单工厂设计模式」黑铁 III
    某神秘公司 RESTful、共用接口、前后端分离、接口约定的实践
    这40张图送给单身程序员,情人节请一笑而过!
    科技圈晒开工福利!2019一起定个小目标!
    IDEA一定要懂的32条快捷键
    假期结束了,我相信未来会更好!
    有一种痛,叫 “今年没有年终奖”!!!
  • 原文地址:https://www.cnblogs.com/shenjianping/p/14866577.html
Copyright © 2011-2022 走看看