如何保护Django公开端点仅允许React应用访问?
保护Django /helloKitty端点的实用方案
要保护你的Django /helloKitty 端点,只允许你的React应用访问,这里提供几种实用的实现方案,根据你的部署场景选择即可:
方案1:验证请求来源(适合同域/固定可信域名场景)
如果你的React应用和Django后端同域部署,或者前端域名是固定且可信的,可以通过检查请求的Origin或Referer头来拦截非法访问。
修改views.py中的helloKitty函数:
from django.http import HttpResponseForbidden, HttpResponse import pandas as pd def helloKitty(request): # 替换为你的React应用实际域名,生产环境注意使用HTTPS allowed_origins = ['http://localhost:3000', 'https://your-production-react-domain.com'] origin = request.headers.get('Origin') referer = request.headers.get('Referer') # 验证请求来源是否在允许列表内 valid_source = False if origin in allowed_origins: valid_source = True elif referer: # 检查Referer是否包含允许的域名 valid_source = any(domain in referer for domain in allowed_origins) if not valid_source: return HttpResponseForbidden("无访问权限") hello = pd.read_csv('static/data/helloKitty_data.csv') hello = hello.to_json(orient='records') return HttpResponse(hello)
方案2:API密钥验证(适合跨域/独立部署场景)
给前端分配唯一API密钥,请求时在请求头中携带,后端验证密钥有效性。
后端修改(views.py)
from django.http import HttpResponseForbidden, HttpResponse import pandas as pd import os def helloKitty(request): # 建议从环境变量读取密钥,避免硬编码泄露 VALID_API_KEY = os.environ.get('KITTY_API_KEY', 'your-default-secret-key') api_key = request.headers.get('X-API-Key') if api_key != VALID_API_KEY: return HttpResponseForbidden("无效的API密钥") hello = pd.read_csv('static/data/helloKitty_data.csv') hello = hello.to_json(orient='records') return HttpResponse(hello)
前端修改(React zustand store)
在axios请求中添加X-API-Key头,注意生产环境用环境变量注入密钥:
import React from "react"; import { create } from 'zustand'; import axios from 'axios'; const kittyStore = create((set) => ({ kitten: [], fetchKitty: async () => { const response = await axios.get('/helloKitty', { headers: { // 开发环境可直接写,生产环境用process.env.REACT_APP_KITTY_API_KEY 'X-API-Key': process.env.REACT_APP_KITTY_API_KEY || 'your-default-secret-key' } }); const hello = response.data.map((h) => ({ name: h.name, age: h.age, })); set({ kitten: hello }) }, })); export default kittyStore;
提示:React项目中,环境变量需要以
REACT_APP_开头,放在.env文件中,部署时由服务器注入。
方案3:JWT认证(需用户登录的场景)
如果你的应用需要用户登录后才能访问数据,使用JWT令牌进行身份验证是更安全的选择。
1. 安装依赖
pip install djangorestframework-simplejwt
2. 配置Django settings.py
INSTALLED_APPS = [ # 已有应用 'rest_framework', 'rest_framework_simplejwt', ] REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': ( 'rest_framework_simplejwt.authentication.JWTAuthentication', ), }
3. 添加JWT路由到urls.py
from django.urls import path from . import views from rest_framework_simplejwt.views import TokenObtainPairView, TokenRefreshView app_name = 'Main' urlpatterns = [ path("helloKitty/", views.helloKitty, name='helloKitty'), path('api/token/', TokenObtainPairView.as_view(), name='token_obtain_pair'), path('api/token/refresh/', TokenRefreshView.as_view(), name='token_refresh'), ]
4. 修改视图函数启用JWT验证
from rest_framework.decorators import api_view, permission_classes from rest_framework.permissions import IsAuthenticated from rest_framework.response import Response import pandas as pd @api_view(['GET']) @permission_classes([IsAuthenticated]) def helloKitty(request): hello = pd.read_csv('static/data/helloKitty_data.csv') return Response(hello.to_json(orient='records'))
前端修改(获取并携带JWT令牌)
// 先实现登录获取令牌(示例) const login = async (username, password) => { const res = await axios.post('/api/token/', { username, password }); localStorage.setItem('access_token', res.data.access); }; // 请求数据时携带令牌 const kittyStore = create((set) => ({ kitten: [], fetchKitty: async () => { const token = localStorage.getItem('access_token'); const response = await axios.get('/helloKitty', { headers: { 'Authorization': `Bearer ${token}` } }); const hello = response.data.map((h) => ({ name: h.name, age: h.age, })); set({ kitten: hello }) }, }));
内容的提问来源于stack exchange,提问作者x945
相关产品推荐
相关产品推荐

