django-security
Django 安全最佳实践、认证、授权、CSRF 防护、SQL 注入预防、XSS 预防和安全部署配置。
DeepseekModel
官方收录技能
质量 优秀 · 90
v1.0.0
获取
https://deepseekmodel.com/api/download.php?id=affaan-m-ecc-docs-zh-cn-skills-django-security-skill-md&format=skill
下载 .skill
标准格式,含 system_prompt 与 model_config,导入任意 Agent 框架即可使用
.skill 文件中 system_prompt 字段的实际内容。
name django-security description Django 安全最佳实践、认证、授权、CSRF 防护、SQL 注入预防、XSS 预防和安全部署配置。 origin ECC Django 安全最佳实践 保护 Django 应用程序免受常见漏洞侵害的全面安全指南。 何时启用 设置 Django 认证和授权时 实现用户权限和角色时 配置生产环境安全设置时 审查 Django 应用程序的安全问题时 将 Django 应用程序部署到生产环境时 核心安全设置 生产环境设置配置 # settings/production.py import os DEBUG = False # CRITICAL: Never use True in production ALLOWED_HOSTS = os.environ.get( 'ALLOWED_HOSTS' , '' ).split( ',' ) # Security headers SECURE_SSL_REDIRECT = True SESSION_COOKIE_SECURE = True CSRF_COOKIE_SECURE = True SECURE_HSTS_SECONDS = 31536000 # 1 year SECURE_HSTS_INCLUDE_SUBDOMAINS = True SECURE_HSTS_PRELOAD = True SECURE_CONTENT_TYPE_NOSNIFF = True SECURE_BROWSER_XSS_FILTER = True X_FRAME_OPTIONS = 'DENY' # HTTPS and Cookies SESSION_COOKIE_HTTPONLY = True CSRF_COOKIE_HTTPONLY = True SESSION_COOKIE_SAMESITE = 'Lax' CSRF_COOKIE_SAMESITE = 'Lax' # Secret key (must be set via environment variable) SECRET_KEY = os.environ.get( 'DJANGO_SECRET_KEY' ) if not SECRET_KEY: raise ImproperlyConfigured( 'DJANGO_SECRET_KEY environment variable is required' ) # Password validation AUTH_PASSWORD_VALIDATORS = [ { 'NAME' : 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator' , }, { 'NAME' : 'django.contrib.auth.password_validation.MinimumLengthValidator' , 'OPTIONS' : { 'min_length' : 12 , } }, { 'NAME' : 'django.contrib.auth.password_validation.CommonPasswordValidator' , }, { 'NAME' : 'django.contrib.auth.password_validation.NumericPasswordValidator' , }, ] 认证 自定义用户模型 # apps/users/models.py from django.contrib.auth.models import AbstractUser from django.db import models class User ( AbstractUser ): """Custom user model for better security.""" email = models.EmailField(unique= True ) phone = models.CharField(max_length= 20 , blank= True ) USERNAME_FIELD = 'email' # Use email as username REQUIRED_FIELDS = [ 'username' ] class Meta : db_table = 'users' verbose_name = 'User' verbose_name_plural = 'Users' def __str__ ( self ): return self .email # settings/base.py AUTH_USER_MODEL = 'users.User' 密码哈希 # Django uses PBKDF2 by default. For stronger security: PASSWORD_HASHERS = [ 'django.contrib.auth.hashers.Argon2PasswordHasher' , 'django.contrib.auth.hashers.PBKDF2PasswordHasher' , 'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher' , 'django.contrib.auth.hashers.BCryptSHA256PasswordHasher' , ] 会话管理 # Session configuration SESSION_ENGINE = 'django.contrib.sessions.backends.cache' # Or 'db' SESSION_CACHE_ALIAS = 'default' SESSION_COOKIE_AGE = 3600 * 24 * 7 # 1 week SESSION_SAVE_EVERY_REQUEST = False SESSION_EXPIRE_AT_BROWSER_CLOSE = False # Better UX, but less secure 授权 权限 # models.py from django.db import models from django.contrib.auth.models import Permission class Post (models.Model): title = models.CharField(max_length= 200 ) content = models.TextField() author = models.ForeignKey(User, on_delete=models.CASCADE) class Meta : permissions = [ ( 'can_publish' , 'Can publish posts' ), ( 'can_edit_others' , 'Can edit posts of others' ), ] def user_can_edit ( self, user ): """Check if user can edit this post.""" return self .author == user or user.has_perm( 'app.can_edit_others' ) # views.py from django.contrib.auth.mixins import LoginRequiredMixin, PermissionRequiredMixin from django.views.generic import UpdateView class PostUpdateView (LoginRequiredMixin, PermissionRequiredMixin, UpdateView): model = Post permission_required = 'app.can_edit_others' raise_exception = True # Return 403 instead of redirect def get_queryset ( self ): """Only allow users to edit their own posts.""" return Post.objects. filter (author= self .request.user) 自定义权限 # permissions.py from rest_framework import permissions class IsOwnerOrReadOnly (permissions.BasePermission): """Allow only owners to edit objects.""" def has_object_permission ( self, request, view, obj ): # Read permissions allowed for any request if request.method in permissions.SAFE_METHODS: return True # Write permissions only for owner return obj.author == request.user class IsAdminOrReadOnly (permissions.BasePermission): """Allow admins to do anything, others read-only.""" def has_permission ( self, request, view ): if request.method in permissions.SAFE_METHODS: return True return request.user and request.user.is_staff class IsVerifiedUser (permissions.BasePermission): """Allow only verified users.""" def has_permission ( self, request, view ): return request.user and request.user.is_authenticated and request.user.is_verified 基于角色的访问控制 (RBAC) # models.py from django.contrib.auth.models import AbstractUser, Group class User ( AbstractUser ): ROLE_CHOICES = [ ( 'admin' , 'Administrator' ), ( 'moderator' , 'Moderator' ), ( 'user' , 'Regular User' ), ] role = models.CharField(max_length= 20 , choices=ROLE_CHOICES, default= 'user' ) def is_admin ( self ): return self .role == 'admin' or self .is_superuser def is_moderator ( self ): return self .role in [ 'admin' , 'moderator' ] # Mixins class AdminRequiredMixin : """Mixin to require admin role.""" def dispatch ( self, request, *args, **kwargs ): if not request.user.is_authenticated or not request.user.is_admin(): from django.core.exceptions import PermissionDenied raise PermissionDenied return super ().dispatch(request, *args, **kwargs) SQL 注入防护 Django ORM 保护 # GOOD: Django ORM automatically escapes parameters def get_user ( username ): return User.objects.get(username=username) # Safe # GOOD: Using parameters with raw() def search_users ( query ): return User.objects.raw( 'SELECT * FROM users WHERE username = %s' , [query]) # BAD: Never directly interpolate user input def get_user_bad ( username ): return User.objects.raw( f'SELECT * FROM users WHERE username = {username} ' ) # VULNERABLE! # GOOD: Using filter with proper escaping def get_users_by_email ( email ): return User.objects. filter (email__iexact=email) # Safe # GOOD: Using Q objects for complex queries from django.db.models import Q def search_users_complex ( query ): return User.objects. filter ( Q(username__icontains=query) | Q(email__icontains=query) ) # Safe 使用 raw() 的额外安全措施 # If you must use raw SQL, always use parameters User.objects.raw( 'SELECT * FROM users WHERE email = %s AND status = %s' , [user_input_email, status] ) XSS 防护 模板转义 {# Django auto-escapes variables by default - SAFE #} {{ user_input }} {# Escaped HTML #} {# Explicitly mark safe only for trusted content #} {{ trusted_html|safe }} {# Not escaped #} {# Use template filters for safe HTML #} {{ user_input|escape }} {# Same as default #} {{ user_input|striptags }} {# Remove all HTML tags #} {# JavaScript escaping #} <script> var username = {{ username|escapejs }}; </script> 安全字符串处理 from django.utils.safestring import mark_safe from django.utils.html import escape # BAD: Never mark user input as safe without escaping def render_bad ( user_input ): return mark_safe(user_input) # VULNERABLE! # GOOD: Escape first, then mark safe def render_good ( user_input ): return mark_safe(escape(user_input)) # GOOD: Use format_html for HTML with variables from django.utils.html import format_html def greet_user ( username ): return format_html( '<span class="user">{}</span>' , escape(username)) HTTP 头部 # settings.py SECURE_CONTENT_TYPE_NOSNIFF = True # Prevent MIME sniffing SECURE_BROWSER_XSS_FILTER = True # Enable XSS filter X_FRAME_OPTIONS = 'DENY' # Prevent clickjacking # Custom middleware from django.conf import settings class SecurityHeaderMiddleware : def __init__ ( self, get_response ): self .get_response = get_response def __call__ ( self, request ): response = self .get_response(request) response[ 'X-Content-Type-Options' ] = 'nosniff' response[ 'X-Frame-Options' ] = 'DENY' response[ 'X-XSS-Protection' ] = '1; mode=block' response[ 'Content-Security-Policy' ] = "default-src 'self'" return response CSRF 防护 默认 CSRF 防护 # settings.py - CSRF is enabled by default CSRF_COOKIE_SECURE = True # Only send over HTTPS CSRF_COOKIE_HTTPONLY = True # Prevent JavaScript access CSRF_COOKIE_SAMESITE = 'Lax' # Prevent CSRF in some cases CSRF_TRUSTED_ORIGINS = [ 'https://example.com' ] # Trusted domains # Template usage <form method= "post" > {% csrf_token %} {{ form.as_p }} <button type = "submit" >Submit</button> </form> # AJAX requests function getCookie(name) { let cookieValue = null; if (document.cookie && document.cookie !== '' ) { const cookies = document.cookie.split( ';' ); for (let i = 0 ; i < cookies.length; i++) { const cookie = cookies[i].trim(); if (cookie.substring( 0 , name.length + 1 ) === (name + '=' )) { cookieValue = decodeURIComponent(cookie.substring(name.length + 1 )); break ; } } } return cookieValue; } fetch( '/api/endpoint/' , { method: 'POST' , headers: { 'X-CSRFToken' : getCookie( 'csrftoken' ), 'Content-Type' : 'application/json' , }, body: JSON.stringify(data) }); 豁免视图(谨慎使用) from django.views.decorators.csrf import csrf_exempt @csrf_exempt # Only use when absolutely necessary! def webhook_view ( request ): # Webhook from external service pass 文件上传安全 文件验证 import os from django.core.exceptions import ValidationError def validate_file_extension ( value ): """Validate file extension.""" ext = os.path.splitext(value.name)[ 1 ] valid_extensions = [ '.jpg' , '.jpeg' , '.png' , '.gif' , '.pdf' ] if not ext.lower() in valid_extensions: raise ValidationError( 'Unsupported file extension.' ) def validate_file_size ( value ): """Validate file size (max 5MB).""" filesize = value.size if filesize > 5 * 1024 * 1024 : raise ValidationError( 'File too large. Max size is 5MB.' ) # models.py class Document (models.Model): file = models.FileField( upload_to= 'documents/' , validators=[validate_file_extension, validate_file_size] ) 安全的文件存储 # settings.py MEDIA_ROOT = '/var/www/media/' MEDIA_URL = '/media/' # Use a separate domain for media in production MEDIA_DOMAIN = 'https://media.example.com' # Don't serve user uploads directly # Use whitenoise or a CDN for static files # Use a separate server or S3 for media files API 安全 速率限制 # settings.py REST_FRAMEWORK = { 'DEFAULT_THROTTLE_CLASSES' : [ 'rest_framework.throttling.AnonRateThrottle' , 'rest_framework.throttling.UserRateThrottle' ], 'DEFAULT_THROTTLE_RATES' : { 'anon' : '100/day' , 'user' : '1000/day' , 'upload' : '10/hour' , } } # Custom throttle from rest_framework.throttling import UserRateThrottle class BurstRateThrottle ( UserRateThrottle ): scope = 'burst' rate = '60/min' class SustainedRateThrottle ( UserRateThrottle ): scope = 'sustained' rate = '1000/day' API 认证 # settings.py
Agent 识别该技能的关键词,点击任意一个即可复制。
该技能未提供触发词。
下载的 .skill 包内含以下字段。
| 字段 | 说明 |
|---|---|
| format | 格式标识(skill/v1) |
| skill_id | 技能唯一 ID |
| name | 技能名称 |
| version | 版本号 |
| description | 技能描述 |
| category | 所属分类(数组) |
| trigger_words | 触发词列表 |
| tags | 标签列表 |
| source | 来源标识 |
| source_url | 来源链接(本页地址) |
| exported_at | 导出时间(每次下载生成) |
| system_prompt | 系统提示词正文 |
| model_config | 模型参数:provider / model / temperature / max_tokens / top_p |
| examples | 示例 |
| install_guide | 各平台导入说明(Coze / Dify / Claude / 自定义框架) |