ha'ha
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
认证 API:登录(无需 token)。
|
||||
认证 API:登录(无需 Authorization)。
|
||||
"""
|
||||
import uuid
|
||||
|
||||
@@ -15,14 +15,14 @@ from server.serializers import LoginSerializer
|
||||
|
||||
|
||||
@api_view(["POST"])
|
||||
@authentication_classes([]) # 登录接口不校验 Cookie token,避免未带 Cookie 时被默认权限判为 403
|
||||
@authentication_classes([]) # 登录接口不校验 Authorization
|
||||
@permission_classes([AllowAny])
|
||||
def login(request):
|
||||
"""
|
||||
登录接口(支持 JSON 和 form-data):
|
||||
- 校验用户名/密码
|
||||
- 生成 token,写入数据库
|
||||
- 通过 Set-Cookie 返回 auth_token,前端后续请求自动携带
|
||||
- 返回 token(前端可放到 Authorization 请求头)
|
||||
- 下一次登录会生成新 token,旧 token 自动失效
|
||||
"""
|
||||
ser = LoginSerializer(data=request.data)
|
||||
@@ -40,12 +40,4 @@ def login(request):
|
||||
defaults={"token": token},
|
||||
)
|
||||
|
||||
resp = Response({"token": token})
|
||||
resp.set_cookie(
|
||||
key="auth_token",
|
||||
value=token,
|
||||
httponly=True,
|
||||
max_age=365 * 24 * 60 * 60,
|
||||
samesite="Lax",
|
||||
)
|
||||
return resp
|
||||
return Response({"token": token})
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
DRF 自定义认证后端:从 Cookie 中读取 auth_token 校验。
|
||||
DRF 自定义认证后端:只要请求头包含 Authorization 即视为已认证。
|
||||
"""
|
||||
from rest_framework.authentication import BaseAuthentication
|
||||
from rest_framework.exceptions import AuthenticationFailed
|
||||
|
||||
|
||||
class TokenUser:
|
||||
@@ -17,22 +16,17 @@ class TokenUser:
|
||||
return self.username
|
||||
|
||||
|
||||
class CookieTokenAuthentication(BaseAuthentication):
|
||||
"""
|
||||
从请求 Cookie 中读取 auth_token,查数据库校验。
|
||||
"""
|
||||
class HeaderAuthorizationAuthentication(BaseAuthentication):
|
||||
"""仅要求请求头中存在 Authorization 字段。"""
|
||||
|
||||
def authenticate(self, request):
|
||||
token = request.COOKIES.get("auth_token")
|
||||
if not token:
|
||||
return None # 未携带 token,交给权限类处理
|
||||
if "HTTP_AUTHORIZATION" not in request.META:
|
||||
return None # 未携带 Authorization,交给权限类处理
|
||||
|
||||
# 延迟导入避免循环依赖
|
||||
from server.models import AuthToken
|
||||
# 只要求字段存在,不校验值内容。
|
||||
auth_value = request.headers.get("Authorization", "")
|
||||
return (TokenUser("authorization_header_user"), auth_value)
|
||||
|
||||
try:
|
||||
row = AuthToken.objects.get(token=token)
|
||||
except AuthToken.DoesNotExist:
|
||||
raise AuthenticationFailed("登录已失效,请重新登录")
|
||||
|
||||
return (TokenUser(row.username), token)
|
||||
# 兼容旧配置名
|
||||
CookieTokenAuthentication = HeaderAuthorizationAuthentication
|
||||
|
||||
@@ -52,7 +52,7 @@ DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
|
||||
# ─── DRF ───
|
||||
REST_FRAMEWORK = {
|
||||
"DEFAULT_AUTHENTICATION_CLASSES": [
|
||||
"server.core.authentication.CookieTokenAuthentication",
|
||||
"server.core.authentication.HeaderAuthorizationAuthentication",
|
||||
],
|
||||
"DEFAULT_PERMISSION_CLASSES": [
|
||||
"rest_framework.permissions.IsAuthenticated",
|
||||
|
||||
Reference in New Issue
Block a user