文章
django-ninja-jwt demo
前置教程:
一、基本配置
1、组件安装
pip install django-ninja-jwt
settings.py添加组件
INSTALLED_APPS = [
...
'ninja_extra',
'ninja_jwt',
...
]
2、编辑根api.py
替换api实例化的类
from ninja_jwt.controller import NinjaJWTDefaultController
from ninja_extra import NinjaExtraAPI
api = NinjaExtraAPI(
title="My Project API",
version="1.0.0",
description="A fantastic API built with Django Ninja"
)
api.register_controllers(NinjaJWTDefaultController)
二、测试
以下引用官方测试示例
1、获取token
curl \
-X POST \
-H "Content-Type: application/json" \
-d '{"username": "davidattenborough", "password": "boatymcboatface"}' \
http://localhost:8000/api/token/pair
...
{
"access":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX3BrIjoxLCJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiY29sZF9zdHVmZiI6IuKYgyIsImV4cCI6MTIzNDU2LCJqdGkiOiJmZDJmOWQ1ZTFhN2M0MmU4OTQ5MzVlMzYyYmNhOGJjYSJ9.NHlztMGER7UADHZJlxNG0WSi22a2KaYSfd1S-AuT7lU",
"refresh":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX3BrIjoxLCJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImNvbGRfc3R1ZmYiOiLimIMiLCJleHAiOjIzNDU2NywianRpIjoiZGUxMmY0ZTY3MDY4NDI3ODg5ZjE1YWMyNzcwZGEwNTEifQ.aEoAYkSJjoWH1boshQAaTkf8G3yn0kapko6HFRt7Rh4"
}
你可以使用返回的访问令牌来证明对受保护视图的认证:
curl \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX3BrIjoxLCJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiY29sZF9zdHVmZiI6IuKYgyIsImV4cCI6MTIzNDU2LCJqdGkiOiJmZDJmOWQ1ZTFhN2M0MmU4OTQ5MzVlMzYyYmNhOGJjYSJ9.NHlztMGER7UADHZJlxNG0WSi22a2KaYSfd1S-AuT7lU" \
http://localhost:8000/api/some-protected-view/
当这个短期访问令牌过期时,你可以使用长期的刷新令牌来获取另一个访问令牌:
curl \
-X POST \
-H "Content-Type: application/json" \
-d '{"refresh":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX3BrIjoxLCJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImNvbGRfc3R1ZmYiOiLimIMiLCJleHAiOjIzNDU2NywianRpIjoiZGUxMmY0ZTY3MDY4NDI3ODg5ZjE1YWMyNzcwZGEwNTEifQ.aEoAYkSJjoWH1boshQAaTkf8G3yn0kapko6HFRt7Rh4"}' \
http://localhost:8000/api/token/refresh/
...
{"access":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX3BrIjoxLCJ0b2tlbl90eXBlIjoiYWNjZX...", "refresh":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX3BrIjoxLCJ0b2tlbl90eXBlIjoicmVm..."}
如果你计划使用某些数字签名算法(即 RSA 和 ECDSA;访问 PyJWT 以获取其他算法)来编码或解码令牌, 你将需要安装加密库 cryptography_ 。这可以明确地安装,或者作为 django-ninja-jwt 要求中的一个必填项进行安装:
pip install django-ninja-jwt[crypto]
在使用 Ninja JWT 的项目的需求文件中,推荐使用 django-ninja-jwt[crypto] 格式, 因为单独的 cryptography 需求行之后可能会被误认为是未使用的需求并被删除
三、路由鉴权
Ninja JWT 使用 Django Ninja 的 HttpBearer
作为对到达你的 API 端点的用户进行身份验证的一种方式。 经过身份验证的用户可以在 request.user
或 request.auth
中找到。
路由身份验证 - Class Based(基于类的)
from ninja_extra import api_controller, route
from ninja_jwt.authentication import JWTAuth
@api_controller
class MyController:
@route.get('/some-endpoint', auth=JWTAuth())
def some_endpoint(self):
...
路由身份验证 - Function Based(基于函数)
from ninja import router
from ninja_jwt.authentication import JWTAuth
router = router('')
@router.get('/some-endpoint', auth=JWTAuth())
def some_endpoint(request):
...
四、Ninja JWT配置
Ninja JWT 的一些行为可以通过在 settings.py 中的设置变量来进行自定义:
# Django project settings.py
from datetime import timedelta
from django.conf import settings
...
NINJA_JWT = {
'ACCESS_TOKEN_LIFETIME': timedelta(minutes=5),
'REFRESH_TOKEN_LIFETIME': timedelta(days=1),
'ROTATE_REFRESH_TOKENS': False,
'BLACKLIST_AFTER_ROTATION': False,
'UPDATE_LAST_LOGIN': False,
'ALGORITHM': 'HS256',
'SIGNING_KEY': settings.SECRET_KEY,
'VERIFYING_KEY': None,
'AUDIENCE': None,
'ISSUER': None,
'JWK_URL': None,
'LEEWAY': 0,
'USER_ID_FIELD': 'id',
'USER_ID_CLAIM': 'user_id',
'USER_AUTHENTICATION_RULE': 'ninja_jwt.authentication.default_user_authentication_rule',
'AUTH_TOKEN_CLASSES': ('ninja_jwt.tokens.AccessToken',),
'TOKEN_TYPE_CLAIM': 'token_type',
'TOKEN_USER_CLASS': 'ninja_jwt.models.TokenUser',
'JTI_CLAIM': 'jti',
'SLIDING_TOKEN_REFRESH_EXP_CLAIM': 'refresh_exp',
'SLIDING_TOKEN_LIFETIME': timedelta(minutes=5),
'SLIDING_TOKEN_REFRESH_LIFETIME': timedelta(days=1),
# For Controller Schemas
# FOR OBTAIN PAIR
'TOKEN_OBTAIN_PAIR_INPUT_SCHEMA': "ninja_jwt.schema.TokenObtainPairInputSchema",
'TOKEN_OBTAIN_PAIR_REFRESH_INPUT_SCHEMA': "ninja_jwt.schema.TokenRefreshInputSchema",
# FOR SLIDING TOKEN
'TOKEN_OBTAIN_SLIDING_INPUT_SCHEMA': "ninja_jwt.schema.TokenObtainSlidingInputSchema",
'TOKEN_OBTAIN_SLIDING_REFRESH_INPUT_SCHEMA':"ninja_jwt.schema.TokenRefreshSlidingInputSchema",
'TOKEN_BLACKLIST_INPUT_SCHEMA': "ninja_jwt.schema.TokenBlacklistInputSchema",
'TOKEN_VERIFY_INPUT_SCHEMA': "ninja_jwt.schema.TokenVerifyInputSchema",
}
ACCESS_TOKEN_LIFETIME(访问令牌有效期)
一个 datetime.timedelta 对象,它指定访问令牌的有效时长。 在令牌生成期间,这个 timedelta 值会被添加到当前的 UTC 时间,以获得令牌默认的 exp 声明值。
REFRESH_TOKEN_LIFETIME(刷新令牌有效期)
一个 datetime.timedelta 对象,它指定刷新令牌的有效时长。 在令牌生成期间,这个 timedelta 值会被添加到当前的 UTC 时间,以获得令牌默认的 exp 声明值。
BLACKLIST_AFTER_ROTATION(旋转后列入黑名单)
当设置为 True 时,如果黑名单应用程序在使用中且 ROTATE_REFRESH_TOKENS 设置为 True, 提交给 TokenRefreshView 的刷新令牌将被添加到黑名单中。 你需要在设置文件中将 'ninja_jwt.token_blacklist', 添加到你的 INSTALLED_APPS 中才能使用此设置。
了解更多关于 /blacklist_app{.interpreted-text role="doc"} 的信息。
UPDATE_LAST_LOGIN(更新最后登录)
当设置为 True 时,在登录(TokenObtainPairView)时会更新 auth_user 表中的 last_login 字段。
警告:更新最后登录将极大地增加数据库事务的数量。 滥用视图的人可能会减慢服务器速度,这可能是一个安全漏洞。 如果你确实想要这样做,至少要用 DRF 限制端点。
五、小结
from ninja import Schema
from ninja_jwt.controller import NinjaJWTDefaultController
from ninja_jwt.authentication import JWTAuth
from ninja_extra import NinjaExtraAPI
from emp.api import router as emp_router
api = NinjaExtraAPI(
title="My Project API",
version="1.0.0",
description="A fantastic API built with Django Ninja"
)
api.register_controllers(NinjaJWTDefaultController)
api.add_router("emp/", emp_router)
class UserSchema(Schema):
username: str
is_authenticated: bool
email: str = None
@api.get("/hello")
def hello(request):
print(request)
return "Hello World!"
@api.get("/me", response=UserSchema, auth=JWTAuth())
def me(request):
return request.user