HOOOS

手把手教你用 Django REST framework + JWT 构建安全的 API 接口(附版本控制与文档)

0 7 Django侠 Django REST frameworkJWT 身份验证API 版本控制
Apple

在现代 Web 开发中,API 接口扮演着至关重要的角色。它们是不同系统之间进行数据交互的桥梁。Django REST framework (DRF) 是一款强大且灵活的工具,可以帮助我们快速构建 RESTful API。结合 JSON Web Tokens (JWT) 可以实现安全的身份验证。本文将一步步指导你如何使用 DRF 和 JWT 构建 API 接口,并考虑到 API 的版本控制、文档生成和安全性。

1. 环境搭建与依赖安装

首先,确保你已经安装了 Python 和 pip。推荐使用 virtualenv 或 conda 创建一个独立的虚拟环境,以避免依赖冲突。

# 创建虚拟环境 (virtualenv)
python -m venv venv

# 激活虚拟环境
# Linux/macOS
source venv/bin/activate
# Windows
.\venv\Scripts\activate

# 安装 Django 和 Django REST framework
pip install django djangorestframework

# 安装 JWT 相关依赖
pip install djangorestframework-simplejwt

2. 创建 Django 项目和应用

创建一个 Django 项目和一个用于 API 的应用。

# 创建 Django 项目
django-admin startproject myapi
cd myapi

# 创建 API 应用
python manage.py startapp api

api 应用添加到 myapi/settings.pyINSTALLED_APPS 中:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework',
    'api',
]

3. 配置 Django REST framework 和 JWT

myapi/settings.py 中配置 DRF 和 JWT:

REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.IsAuthenticated',
    ],
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework_simplejwt.authentication.JWTAuthentication',
    ],
    'DEFAULT_VERSIONING_CLASS': 'rest_framework.versioning.URLPathVersioning',
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
    'PAGE_SIZE': 10
}

SIMPLE_JWT = {
    'ACCESS_TOKEN_LIFETIME': timedelta(minutes=5),
    'REFRESH_TOKEN_LIFETIME': timedelta(days=1),
    'ROTATE_REFRESH_TOKENS': False,
    'BLACKLIST_AFTER_ROTATION': True,

    'ALGORITHM': 'HS256',
    'SIGNING_KEY': SECRET_KEY,
    'VERIFYING_KEY': None,
    'AUTH_HEADER_TYPES': ('Bearer',),
    'USER_ID_FIELD': 'id',
    'USER_ID_CLAIM': 'user_id',

    'AUTH_TOKEN_CLASSES': ('rest_framework_simplejwt.tokens.AccessToken',),
    'TOKEN_TYPE_CLAIM': 'token_type',
}

解释:

  • DEFAULT_PERMISSION_CLASSES: 设置默认的权限类,这里设置为 IsAuthenticated,表示只有认证用户才能访问 API。
  • DEFAULT_AUTHENTICATION_CLASSES: 设置默认的认证类,这里设置为 JWTAuthentication,使用 JWT 进行身份验证。
  • DEFAULT_VERSIONING_CLASS: 设置API版本控制类,这里设置为 URLPathVersioning,通过 URL 路径进行版本控制。
  • SIMPLE_JWT: 配置 JWT 的各项参数,例如 access token 和 refresh token 的过期时间、签名算法等。

4. 创建模型 (Model)

假设我们要创建一个简单的 Product 模型,在 api/models.py 中定义:

from django.db import models

class Product(models.Model):
    name = models.CharField(max_length=200)
    description = models.TextField()
    price = models.DecimalField(max_digits=10, decimal_places=2)
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.name

执行数据库迁移:

python manage.py makemigrations
python manage.py migrate

5. 创建序列化器 (Serializer)

序列化器用于将模型数据转换为 JSON 格式,以及将 JSON 数据转换为模型实例。在 api/serializers.py 中创建 ProductSerializer

from rest_framework import serializers
from .models import Product

class ProductSerializer(serializers.ModelSerializer):
    class Meta:
        model = Product
        fields = '__all__'

6. 创建视图 (View)

视图处理 API 请求并返回响应。在 api/views.py 中创建 ProductViewSet

from rest_framework import viewsets
from .models import Product
from .serializers import ProductSerializer
from rest_framework.permissions import IsAuthenticated
from rest_framework.versioning import URLPathVersioning

class ProductViewSet(viewsets.ModelViewSet):
    queryset = Product.objects.all()
    serializer_class = ProductSerializer
    permission_classes = [IsAuthenticated]
    versioning_class = URLPathVersioning

解释:

  • viewsets.ModelViewSet: 提供了一组默认的 API 操作,例如创建、读取、更新和删除。
  • queryset: 指定要查询的模型数据。
  • serializer_class: 指定要使用的序列化器。
  • permission_classes: 指定权限类,这里使用 IsAuthenticated,确保只有认证用户才能访问。
  • versioning_class: 指定版本控制类,与 settings.py 保持一致

7. 配置 URL

api/urls.py 中配置 API 的 URL:

from django.urls import path, include
from rest_framework.routers import DefaultRouter
from . import views

router = DefaultRouter()
router.register(r'products', views.ProductViewSet, basename='product')

urlpatterns = [
    path('', include(router.urls)),
]

myapi/urls.py 中包含 api 应用的 URL,并添加 JWT 的 token 获取和刷新 endpoint:

from django.urls import path, include
from rest_framework_simplejwt.views import (TokenObtainPairView,TokenRefreshView,)

urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/v1/', include('api.urls')),
    path('api/token/', TokenObtainPairView.as_view(), name='token_obtain_pair'),
    path('api/token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
]

重要: 注意api/v1/,这里体现了API的版本控制,后续升级API只需修改版本号,即可保证旧版本API的正常使用。

8. JWT 身份验证

获取 Token

首先,你需要创建一个用户,可以通过 Django 的 createsuperuser 命令创建超级用户,也可以在 api/serializers.py 中创建用户注册的序列化器和视图。

创建用户后,可以使用 TokenObtainPairView 获取 JWT token。发送 POST 请求到 /api/token/,携带 usernamepassword

{
    "username": "your_username",
    "password": "your_password"
}

成功后,你会收到包含 access token 和 refresh token 的响应:

{
    "access": "...",
    "refresh": "..."
}

使用 Token

在访问受保护的 API 接口时,需要在请求头中添加 Authorization 字段,值为 Bearer <access_token>。例如:

Authorization: Bearer <your_access_token>

刷新 Token

access token 过期后,可以使用 refresh token 刷新。发送 POST 请求到 /api/token/refresh/,携带 refresh token:

{
    "refresh": "..."
}

成功后,你会收到新的 access token:

{
    "access": "..."
}

9. API 版本控制

DRF 提供了多种版本控制方案,例如:

  • URL 路径版本控制 (URLPathVersioning): 如上例所示,在 URL 中包含版本号,例如 /api/v1/products/
  • 查询参数版本控制 (QueryParameterVersioning): 通过查询参数指定版本,例如 /api/products/?version=v1
  • Header 版本控制 (AcceptHeaderVersioning): 通过 Accept header 指定版本。

选择适合你项目的版本控制方案,并在 settings.py 中配置 DEFAULT_VERSIONING_CLASS

10. API 文档生成

可以使用 drf-spectaculardrf-yasg 等工具自动生成 API 文档。

使用 drf-spectacular

pip install drf-spectacular

settings.py 中添加 drf_spectacularINSTALLED_APPS

INSTALLED_APPS = [
    ...
    'drf_spectacular',
]

urls.py 中添加 schema 的 URL:

from drf_spectacular.views import SpectacularAPIView, SpectacularRedocView, SpectacularSwaggerView

urlpatterns = [
    ...
    path('api/schema/', SpectacularAPIView.as_view(), name='schema'),
    # Optional UI:
    path('api/schema/swagger-ui/', SpectacularSwaggerView.as_view(url_name='schema'), name='swagger-ui'),
    path('api/schema/redoc/', SpectacularRedocView.as_view(url_name='schema'), name='redoc'),
]

现在,你可以通过 /api/schema/swagger-ui//api/schema/redoc/ 访问 API 文档。

11. 安全性注意事项

  • 使用 HTTPS: 确保你的 API 使用 HTTPS 协议,以加密数据传输。
  • 验证所有输入: 对所有输入数据进行验证,以防止 SQL 注入、XSS 等攻击。
  • 限制请求频率: 使用 throttling 限制 API 请求频率,以防止 DDoS 攻击。
  • 保护敏感数据: 不要在 API 响应中返回敏感数据,例如密码、信用卡信息等。
  • 定期更新依赖: 定期更新 Django、DRF 和其他依赖库,以修复安全漏洞。
  • CORS配置: 配置CORS (Cross-Origin Resource Sharing),允许特定的域名访问你的API,防止跨域攻击。在settings.py中配置:
    INSTALLED_APPS = [
        ...
        'corsheaders',
    ]
    
    MIDDLEWARE = [
        'corsheaders.middleware.CorsMiddleware',
        ...
    ]
    
    CORS_ALLOWED_ORIGINS = [
        "https://example.com",
        "http://localhost:8080",
    ]
    

12. 总结

本文详细介绍了如何使用 Django REST framework 和 JWT 构建安全的 API 接口,并考虑了 API 的版本控制、文档生成和安全性。希望本文能够帮助你快速上手并构建高质量的 API。当然,实际开发中还需要根据具体需求进行调整和优化。记住,安全永远是第一位的!

点评评价

captcha
健康