FastAPI(59)- 详解使用 OAuth2PasswordBearer + JWT 认证(上)

简介: FastAPI(59)- 详解使用 OAuth2PasswordBearer + JWT 认证(上)

JWT


  • JSON Web Tokens
  • 它是一个将 JSON 对象编码为密集且没有空格的长字符串的标准
  • 使用 JWT token 和安全密码 hash 使应用程序真正安全

 

JWT 小栗子

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

  • 它还没有加密,因此任何人都可以从该字符串中恢复信息
  • 但是已经加签了,因此,当收到发出的 token 时,可以验证是否实际发出了它
  • 创建一个有效期为 1 周的 token,然后当用户第二天带着 token 回来时,知道该用户仍然登录到系统中
  • 一周后,令牌将过期,用户将无法获得授权,必须重新登录以获取新的 token
  • 如果用户(或第三方)试图修改 token 以更改过期时间,将能够发现它,因为签名不匹配

 

前提

需要安装 python-jose 来在 Python 中生成和验证 JWT token

pip install python-jose

pip install cryptography

 

JWT 流程


  • 前端登录提交用户名、密码
  • 后端拿到用户名、密码进行验证,如果没问题,则返回 token
  • 前端访问需要认证的 url 时携带 token
  • 后端拿到 token 进行验证
  • 验证通过返回用户信息及访问的 url 信息


image.png


hash 密码


前提

  • 数据库存储的密码不能是明文的,需要加密
  • PassLib 是一个用于处理哈希密码的包
  • 推荐的算法是 「Bcrypt

pip install passlib

pip install bcrypt

 

包含的功能

  • hash 密码
  • 验证 hash 密码是否一致
  • 通过用户名、密码验证用户

 

hash 密码

# 导入 CryptContext
from passlib.context import CryptContext
pwd_context = CryptContext(schemes=['bcrypt'], deprecated="auto")
# 密码加密
def hash_password(password: str) -> str:
    return pwd_context.hash(password)


验证 hash 密码是否一致

# 验证密码

def verify_password(plain_password, hashed_password):

   return pwd_context.verify(plain_password, hashed_password)

 

通过用户名、密码验证用户

# 模拟从数据库中根据用户名查找用户
def get_user(db, username: str):
    if username in db:
        user_dict = db[username]
        return UserInDB(**user_dict)
# 根据用户名、密码来验证用户
def authenticate_user(db, username: str, password: str):
    # 1、通过用户名模拟去数据库查找用户
    user = get_user(db, username)
    if not user:
        # 2、用户不存在
        return False
    if not verify_password(password, user.hashed_password):
        # 3、密码验证失败
        return False
    # 4、验证通过,返回用户信息
    return user


处理 JWT token


生成用于签名 JWT token 的随机密钥

在命令行敲

> openssl rand -hex 32

dc393487a84ddf9da61fe0180ef295cf0642ecbc5d678a1589ef2e26b35fce9c

 

常量池

方便后续复用

# 常量池
# 通过 openssl rand -hex 32 生成的随机密钥
SECRET_KEY = "dc393487a84ddf9da61fe0180ef295cf0642ecbc5d678a1589ef2e26b35fce9c"
# 加密算法
ALGORITHM = "HS256"
# 过期时间,分钟
ACCESS_TOKEN_EXPIRE_MINUTES = 30


创建生成 JWT token 需要用的 Pydantic Model

其实不创建也没事,但这里为了规范和数据校验功能,还是建吧

# 返回给客户端的 Token Model
class Token(BaseModel):
    access_token: str
    token_type: str
class TokenData(BaseModel):
    username: Optional[str] = None


生成 JWT token

# 导入 JWT 相关库
from jose import JWTError, jwt
# 用户名、密码验证成功后,生成 token
def create_access_token(
        data: dict,
        expires_delta: Optional[timedelta] = None):
    to_encode = data.copy()
    if expires_delta:
        expire = datetime.utcnow() + expires_delta
    else:
        expire = datetime.utcnow() + timedelta(minutes=15)
    to_encode.update({"exp": expire})
    # 加密
    encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
    return encoded_jwt


修改 get_current_user


获取 token 后解码并获取用户

# 导入 JWT 相关库
from jose import JWTError, jwt
# 根据当前用户的 token 获取用户,token 已失效则返回错误码
async def get_current_user(token: str = Depends(oauth2_scheme)):
    credentials_exception = HTTPException(
        status_code=status.HTTP_401_UNAUTHORIZED,
        detail="Could not validate credentials",
        headers={"WWW-Authenticate": "Bearer"},
    )
    try:
        # 1、解码收到的 token
        payload = jwt.decode(token, SECRET_KEY, algorithms=ALGORITHM)
        # 2、拿到 username
        username: str = payload.get("sub")
        if not username:
            # 3、若 token 失效,则返回错误码
            raise credentials_exception
        token_data = TokenData(username=username)
    except JWTError:
        raise credentials_exception
    # 4、获取用户
    user = get_user(fake_users_db, username=token_data.username)
    if not user:
        raise credentials_exception
    # 5、返回用户
    return user
相关文章
|
1月前
|
安全 Java Spring
Spring Security+jwt实现认证
Spring Security+jwt实现认证
|
2月前
|
JSON JavaScript 数据格式
jwt-auth插件实现了基于JWT(JSON Web Tokens)进行认证鉴权的功能。
jwt-auth插件实现了基于JWT(JSON Web Tokens)进行认证鉴权的功能。
45 1
|
1月前
|
安全 数据安全/隐私保护
Springboot+Spring security +jwt认证+动态授权
Springboot+Spring security +jwt认证+动态授权
|
4天前
|
JSON SpringCloudAlibaba Cloud Native
SpringCloudAlibaba:4.3云原生网关higress的JWT 认证
SpringCloudAlibaba:4.3云原生网关higress的JWT 认证
12 1
|
14天前
|
运维 Serverless API
Serverless 应用引擎产品使用之阿里函数计算中要关掉http触发器的jwt认证才可以进行性能探测如何解决
阿里云Serverless 应用引擎(SAE)提供了完整的微服务应用生命周期管理能力,包括应用部署、服务治理、开发运维、资源管理等功能,并通过扩展功能支持多环境管理、API Gateway、事件驱动等高级应用场景,帮助企业快速构建、部署、运维和扩展微服务架构,实现Serverless化的应用部署与运维模式。以下是对SAE产品使用合集的概述,包括应用管理、服务治理、开发运维、资源管理等方面。
13 1
|
14天前
|
JSON 安全 API
【专栏】四种REST API身份验证方法:基本认证、OAuth、JSON Web Token(JWT)和API密钥
【4月更文挑战第28天】本文探讨了四种REST API身份验证方法:基本认证、OAuth、JSON Web Token(JWT)和API密钥。基本认证简单但不安全;OAuth适用于授权第三方应用;JWT提供安全的身份验证信息传递;API密钥适合内部使用。选择方法时需平衡安全性、用户体验和开发复杂性。
|
1月前
|
负载均衡 Cloud Native 安全
云原生最佳实践系列 6:MSE 云原生网关使用 JWT 进行认证鉴权
本文档介绍了如何在 MSE(Microservices Engine)云原生网关中集成JWT进行全局认证鉴权。
|
1月前
|
JSON JavaScript 数据格式
jwt-auth插件实现了基于JWT(JSON Web Tokens)进行认证鉴权的功能
jwt-auth插件实现了基于JWT(JSON Web Tokens)进行认证鉴权的功能
39 1
|
2月前
|
JSON 安全 API
在Python Web开发过程中:请简要介绍OAuth和JWT两种认证方式,并说明何时使用它们。
OAuth是开放授权协议,用于第三方应用安全访问用户资源;JWT是JSON格式的安全令牌,用于传递身份和权限。OAuth适合第三方登录和API访问,JWT适用于单点登录和分布式系统中的身份验证。选择取决于应用场景,两者都需确保安全实施,如加密和签名验证。
|
4月前
|
安全 Java 数据库
SpringSecurity+JWT前后端分离架构登录认证
在SpringSecurity实现前后端分离登录token认证详解_springsecurity前后端分离登录认证-CSDN博客基础上进行重构,实现前后端分离架构登录认证,基本思想相同,借鉴开源Gitee代码进行改造,具有更好的代码规范。
185 1