ha'ha
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
"""
|
"""
|
||||||
认证 API:登录(无需 token)。
|
认证 API:登录(无需 Authorization)。
|
||||||
"""
|
"""
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
@@ -15,14 +15,14 @@ from server.serializers import LoginSerializer
|
|||||||
|
|
||||||
|
|
||||||
@api_view(["POST"])
|
@api_view(["POST"])
|
||||||
@authentication_classes([]) # 登录接口不校验 Cookie token,避免未带 Cookie 时被默认权限判为 403
|
@authentication_classes([]) # 登录接口不校验 Authorization
|
||||||
@permission_classes([AllowAny])
|
@permission_classes([AllowAny])
|
||||||
def login(request):
|
def login(request):
|
||||||
"""
|
"""
|
||||||
登录接口(支持 JSON 和 form-data):
|
登录接口(支持 JSON 和 form-data):
|
||||||
- 校验用户名/密码
|
- 校验用户名/密码
|
||||||
- 生成 token,写入数据库
|
- 生成 token,写入数据库
|
||||||
- 通过 Set-Cookie 返回 auth_token,前端后续请求自动携带
|
- 返回 token(前端可放到 Authorization 请求头)
|
||||||
- 下一次登录会生成新 token,旧 token 自动失效
|
- 下一次登录会生成新 token,旧 token 自动失效
|
||||||
"""
|
"""
|
||||||
ser = LoginSerializer(data=request.data)
|
ser = LoginSerializer(data=request.data)
|
||||||
@@ -40,12 +40,4 @@ def login(request):
|
|||||||
defaults={"token": token},
|
defaults={"token": token},
|
||||||
)
|
)
|
||||||
|
|
||||||
resp = Response({"token": token})
|
return Response({"token": token})
|
||||||
resp.set_cookie(
|
|
||||||
key="auth_token",
|
|
||||||
value=token,
|
|
||||||
httponly=True,
|
|
||||||
max_age=365 * 24 * 60 * 60,
|
|
||||||
samesite="Lax",
|
|
||||||
)
|
|
||||||
return resp
|
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
"""
|
"""
|
||||||
DRF 自定义认证后端:从 Cookie 中读取 auth_token 校验。
|
DRF 自定义认证后端:只要请求头包含 Authorization 即视为已认证。
|
||||||
"""
|
"""
|
||||||
from rest_framework.authentication import BaseAuthentication
|
from rest_framework.authentication import BaseAuthentication
|
||||||
from rest_framework.exceptions import AuthenticationFailed
|
|
||||||
|
|
||||||
|
|
||||||
class TokenUser:
|
class TokenUser:
|
||||||
@@ -17,22 +16,17 @@ class TokenUser:
|
|||||||
return self.username
|
return self.username
|
||||||
|
|
||||||
|
|
||||||
class CookieTokenAuthentication(BaseAuthentication):
|
class HeaderAuthorizationAuthentication(BaseAuthentication):
|
||||||
"""
|
"""仅要求请求头中存在 Authorization 字段。"""
|
||||||
从请求 Cookie 中读取 auth_token,查数据库校验。
|
|
||||||
"""
|
|
||||||
|
|
||||||
def authenticate(self, request):
|
def authenticate(self, request):
|
||||||
token = request.COOKIES.get("auth_token")
|
if "HTTP_AUTHORIZATION" not in request.META:
|
||||||
if not token:
|
return None # 未携带 Authorization,交给权限类处理
|
||||||
return None # 未携带 token,交给权限类处理
|
|
||||||
|
|
||||||
# 延迟导入避免循环依赖
|
# 只要求字段存在,不校验值内容。
|
||||||
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 ───
|
# ─── DRF ───
|
||||||
REST_FRAMEWORK = {
|
REST_FRAMEWORK = {
|
||||||
"DEFAULT_AUTHENTICATION_CLASSES": [
|
"DEFAULT_AUTHENTICATION_CLASSES": [
|
||||||
"server.core.authentication.CookieTokenAuthentication",
|
"server.core.authentication.HeaderAuthorizationAuthentication",
|
||||||
],
|
],
|
||||||
"DEFAULT_PERMISSION_CLASSES": [
|
"DEFAULT_PERMISSION_CLASSES": [
|
||||||
"rest_framework.permissions.IsAuthenticated",
|
"rest_framework.permissions.IsAuthenticated",
|
||||||
|
|||||||
BIN
下载 (1).png
Normal file
BIN
下载 (1).png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 111 KiB |
11
测试/test.py
11
测试/test.py
@@ -1,20 +1,17 @@
|
|||||||
import requests
|
import requests
|
||||||
|
|
||||||
url = "http://8.137.99.82:9000/api/auth/login"
|
url = "http://8.137.99.82:9000/api/accounts"
|
||||||
|
|
||||||
payload={}
|
payload={}
|
||||||
files=[
|
|
||||||
|
|
||||||
]
|
|
||||||
headers = {
|
headers = {
|
||||||
|
# 'Authorization': '082af0d858ea4d23a905c82bab753d15',
|
||||||
'User-Agent': 'Apifox/1.0.0 (https://apifox.com)',
|
'User-Agent': 'Apifox/1.0.0 (https://apifox.com)',
|
||||||
'Accept': '*/*',
|
'Accept': '*/*',
|
||||||
'Host': '8.137.99.82:9000',
|
'Host': '8.137.99.82:9000',
|
||||||
'Connection': 'keep-alive',
|
'Connection': 'keep-alive',
|
||||||
'Content-Type': 'multipart/form-data; boundary=--------------------------967987379917827495982839',
|
'Cookie': 'auth_token=082af0d858ea4d23a905c82bab753d15'
|
||||||
'Cookie': 'auth_token=c0ceff1a701e49538965813027f80edb'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
response = requests.request("POST", url, headers=headers, data=payload, files=files)
|
response = requests.request("GET", url, headers=headers, data=payload)
|
||||||
|
|
||||||
print(response.text)
|
print(response.text)
|
||||||
|
|||||||
Reference in New Issue
Block a user