大数据

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