You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Django REST Framework中实现服务端用户会话维护?

Absolutely! Using server-side sessions instead of storing OAuth access tokens in client-side local storage is a fantastic way to tighten up your security. The key win here is that sensitive authentication data never leaves the server (only a session ID does, which is far harder to exploit if configured correctly). Let’s walk through exactly how to implement this in Django REST Framework (DRF):

1. Enable Django's Core Session & Auth Infrastructure

First, make sure Django's built-in session and auth systems are active—they're required for DRF's session authentication to work. Check your settings.py:

# settings.py
INSTALLED_APPS = [
    # ... your other apps
    'django.contrib.sessions',
    'django.contrib.auth',
]

MIDDLEWARE = [
    # ... other middleware
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
]

These are enabled by default in most Django projects, but it’s worth double-checking.

2. Configure DRF to Use Session Authentication

Next, tell DRF to prioritize session authentication. You can set this globally in settings.py, or per-view if you need to mix authentication methods:

Global Configuration

# settings.py
REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework.authentication.SessionAuthentication',
        # Keep other auth classes (like BasicAuth) only if you need them
    ],
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.IsAuthenticated',
    ]
}

Per-View Configuration

If you only want session auth for specific views:

from rest_framework.authentication import SessionAuthentication
from rest_framework.permissions import IsAuthenticated
from rest_framework.views import APIView

class ProtectedDataView(APIView):
    authentication_classes = [SessionAuthentication]
    permission_classes = [IsAuthenticated]

    def get(self, request):
        return Response({'user_id': request.user.id, 'email': request.user.email})
3. Build Login/Logout Endpoints (Replace OAuth Token Flow)

Instead of issuing an access token, you’ll create a session when the user logs in, and destroy it when they log out. Here’s how to build those endpoints:

from rest_framework import status
from rest_framework.response import Response
from rest_framework.views import APIView
from django.contrib.auth import authenticate, login, logout

class LoginView(APIView):
    # Allow unauthenticated users to access this endpoint
    permission_classes = []

    def post(self, request):
        username = request.data.get('username')
        password = request.data.get('password')
        
        # Authenticate the user against Django's auth system
        user = authenticate(request, username=username, password=password)
        
        if user is not None:
            # Create a session for the user
            login(request, user)
            return Response(
                {'message': 'Login successful', 'user': user.username},
                status=status.HTTP_200_OK
            )
        else:
            return Response(
                {'error': 'Invalid username or password'},
                status=status.HTTP_401_UNAUTHORIZED
            )

class LogoutView(APIView):
    def post(self, request):
        # Destroy the user's session
        logout(request)
        return Response(
            {'message': 'Logout successful'},
            status=status.HTTP_200_OK
        )

Don’t forget to wire these up in your urls.py:

from django.urls import path
from .views import LoginView, LogoutView, ProtectedDataView

urlpatterns = [
    path('auth/login/', LoginView.as_view()),
    path('auth/logout/', LogoutView.as_view()),
    path('api/protected/', ProtectedDataView.as_view()),
]
4. Critical Security Hardening Steps

To make sure your session setup is actually secure, tweak these settings in settings.py (especially for production):

# settings.py
# Only send session cookies over HTTPS
SESSION_COOKIE_SECURE = True
# Prevent client-side JS from accessing the session cookie (blocks XSS theft)
SESSION_COOKIE_HTTPONLY = True
# Restrict cookie to same-site requests (blocks CSRF attacks)
SESSION_COOKIE_SAMESITE = 'Strict'
# Set session expiry time (adjust based on your needs)
SESSION_COOKIE_AGE = 3600  # 1 hour
# Refresh session expiry on every request
SESSION_SAVE_EVERY_REQUEST = True

CSRF Protection Note

DRF’s SessionAuthentication requires CSRF protection for non-GET requests. Your frontend will need to include the CSRF token in the request header. Most frontend frameworks can handle this automatically, but here’s a quick JS snippet for vanilla setups:

// Extract CSRF token from cookie
function getCsrfToken() {
    let token = null;
    const cookies = document.cookie.split(';');
    for (const cookie of cookies) {
        const [name, value] = cookie.trim().split('=');
        if (name === 'csrftoken') {
            token = decodeURIComponent(value);
            break;
        }
    }
    return token;
}

// Include token in requests (example with fetch)
fetch('/api/protected/', {
    method: 'POST',
    headers: {
        'X-CSRFToken': getCsrfToken(),
        'Content-Type': 'application/json'
    },
    body: JSON.stringify({ data: 'example' })
});
5. Trade-Offs to Consider
  • Security vs. Statelessness: Sessions require server-side storage (Django uses the database by default; for scalability, you can switch to Redis). OAuth tokens (like JWT) are stateless, but storing them client-side exposes you to XSS risks.
  • Browser Convenience: Browsers automatically send session cookies with every request, so your frontend doesn’t need to manually attach an auth header. With tokens, you’d have to store and send them explicitly.
  • Revocation: Revoking a session is easy—just delete it from the server. Revoking a JWT token is harder unless you use a token blacklist.

内容的提问来源于stack exchange,提问作者Moorani

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 08:05:10