MST

星途 面试题库

面试题:Python的Django在复杂RESTful API架构下如何解决跨域和安全问题

在一个大型、复杂的基于Django的RESTful API项目中,既要处理不同前端应用的跨域请求,又要保证API的安全性(防止诸如SQL注入、XSS攻击等)。详细说明你会如何设计整体解决方案,包括使用的中间件、安全头配置、跨域处理策略以及如何与其他安全服务(如OAuth 2.0认证服务)集成等。
12.6万 热度难度
编程语言Python

知识考点

AI 面试

面试题答案

一键面试

1. 中间件

  • 安全中间件
    • Django自带中间件:启用django.middleware.security.SecurityMiddleware,它会添加一些安全相关的HTTP头,如X-Frame-OptionsX-Content-Type-Options等,有助于防止点击劫持和MIME类型嗅探攻击。
    • CSRF(Cross - Site Request Forgery)中间件:Django默认启用django.middleware.csrf.CsrfViewMiddleware,用于防止跨站请求伪造攻击。对于RESTful API,可根据实际情况(如使用Token认证时)适当调整其配置,在非浏览器场景下可以考虑使用基于Token的认证机制来替代传统的CSRF防护。
  • SQL注入防护
    • ORM(Object - Relational Mapping)使用:在Django项目中,推荐使用Django的ORM进行数据库操作,它会自动对输入进行转义,防止SQL注入。例如,使用filter()exclude()等方法构建查询语句,而不是手动拼接SQL字符串。
    • 参数化查询:如果确实需要执行原生SQL,使用raw()方法并传递参数,确保参数被正确处理。例如:MyModel.objects.raw('SELECT * FROM my_table WHERE column = %s', [param_value])
  • XSS防护
    • 自动转义:Django模板系统默认对变量进行自动转义,以防止XSS攻击。确保在输出数据到模板时不关闭自动转义功能。如果是API返回数据,确保在返回前对可能包含HTML标签的数据进行适当的清理或转义。例如,使用bleach库对输入输出的数据进行清洗,只允许特定的HTML标签和属性。

2. 安全头配置

  • Content - Security - Policy(CSP):通过django - cors - headers库或在settings.py中手动配置,设置Content - Security - Policy头,限制页面可以加载的资源来源,防止XSS攻击。例如:
SECURE_CONTENT_TYPE_NOSNIFF = True
SECURE_BROWSER_XSS_FILTER = True
CSP_DEFAULT_SRC = ("'self'",)
CSP_SCRIPT_SRC = ("'self'",)
CSP_STYLE_SRC = ("'self'",)
  • X - Frame - Options:设置X - Frame - Options头为DENYSAMEORIGIN,防止点击劫持。在settings.py中配置:
X_FRAME_OPTIONS = 'DENY'
  • X - Content - Type - Options:设置X - Content - Type - Options头为nosniff,防止浏览器进行MIME类型嗅探,在settings.py中配置:
SECURE_CONTENT_TYPE_NOSNIFF = True

3. 跨域处理策略

  • 使用django - cors - headers
    • 安装pip install django - cors - headers
    • 配置:在settings.py中添加'corsheaders'INSTALLED_APPS,并配置允许的跨域源。例如:
INSTALLED_APPS = [
    ...
    'corsheaders',
    ...
]
CORS_ALLOWED_ORIGINS = [
    "https://allowed - frontend - 1.com",
    "https://allowed - frontend - 2.com",
]
- **细粒度控制**:可以根据不同的视图或URL模式进行更细粒度的跨域控制,通过`CORS_ALLOW_METHODS`、`CORS_ALLOW_HEADERS`等设置允许的HTTP方法和请求头。
CORS_ALLOW_METHODS = [
    'DELETE',
    'GET',
    'OPTIONS',
    'PATCH',
    'POST',
    'PUT',
]
CORS_ALLOW_HEADERS = [
    'accept',
    'accept - encoding',
    'authorization',
    'content - type',
    'dnt',
    'origin',
    'user - agent',
    'x - csrf - token',
    'x - requested - with',
]

4. 与OAuth 2.0认证服务集成

  • 选择OAuth 2.0库:例如djangorestframework - simplejwt结合django - oauth - toolkit
    • djangorestframework - simplejwt:用于生成和验证JSON Web Tokens(JWT)。安装:pip install djangorestframework - simplejwt。在settings.py中配置:
from datetime import timedelta

SIMPLE_JWT = {
    'ACCESS_TOKEN_LIFETIME': timedelta(minutes = 15),
    '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',

    'JTI_CLAIM': 'jti',

    'SLIDING_TOKEN_REFRESH_EXP_CLAIM':'refresh_exp',
    'SLIDING_TOKEN_LIFETIME': timedelta(minutes = 5),
    'SLIDING_TOKEN_REFRESH_LIFETIME': timedelta(days = 1),
}
- **`django - oauth - toolkit`**:实现OAuth 2.0协议。安装:`pip install django - oauth - toolkit`。在`settings.py`中配置:
INSTALLED_APPS = (
    ...
    'oauth2_provider',
    ...
)
OAUTH2_PROVIDER = {
    # this is the list of available scopes
    'SCOPES': {'read': 'Read scope', 'write': 'Write scope', 'groups': 'Access to your groups'}
}
  • 配置视图和URL
    • 使用oauth2_provider.views中的视图类来处理OAuth 2.0的授权、令牌获取等流程,并在urls.py中配置相应的URL。例如:
from django.urls import path
from oauth2_provider.views import AuthorizationView, TokenView

urlpatterns = [
    path('o/authorize/', AuthorizationView.as_view(), name = 'authorize'),
    path('o/token/', TokenView.as_view(), name = 'token'),
    ...
]
  • 保护API视图:在需要保护的API视图上使用oauth2_provider.contrib.rest_framework.OAuth2Authenticationrest_framework_simplejwt.authentication.JWTAuthentication进行认证,确保只有经过授权的用户才能访问API。例如:
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated
from oauth2_provider.contrib.rest_framework import OAuth2Authentication
from rest_framework_simplejwt.authentication import JWTAuthentication

class MyProtectedAPIView(APIView):
    authentication_classes = [OAuth2Authentication, JWTAuthentication]
    permission_classes = [IsAuthenticated]

    def get(self, request):
        return Response({'message': 'This is a protected API'})