Skip to content

Commit ede0e62

Browse files
author
Lan
committed
feat: 更新管理员登录为简易版jwt
1 parent f2f301f commit ede0e62

20 files changed

+113
-29
lines changed

apps/admin/dependencies.py

Lines changed: 76 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,88 @@
22
# @Author : Lan
33
# @File : depends.py
44
# @Software: PyCharm
5-
from fastapi import Header, HTTPException
5+
from fastapi import Header, HTTPException, Depends
66
from fastapi.requests import Request
7+
import base64
8+
import hmac
9+
import json
10+
import time
711
from core.settings import settings
812
from apps.admin.services import FileService, ConfigService, LocalFileService
913

14+
def create_token(data: dict, expires_in: int = 3600 * 24) -> str:
15+
"""
16+
创建JWT token
17+
:param data: 数据负载
18+
:param expires_in: 过期时间(秒)
19+
"""
20+
header = base64.b64encode(json.dumps({"alg": "HS256", "typ": "JWT"}).encode()).decode()
21+
payload = base64.b64encode(json.dumps({
22+
**data,
23+
"exp": int(time.time()) + expires_in
24+
}).encode()).decode()
25+
26+
signature = hmac.new(
27+
settings.jwt_secret_key.encode(),
28+
f"{header}.{payload}".encode(),
29+
'sha256'
30+
).digest()
31+
signature = base64.b64encode(signature).decode()
32+
33+
return f"{header}.{payload}.{signature}"
1034

11-
async def admin_required(authorization: str = Header(default=None), request: Request = None):
12-
is_admin = (authorization.split(' ')[-1] if authorization else '') == settings.admin_token
13-
if request.url.path.startswith('/share/'):
14-
if not settings.openUpload and not is_admin:
15-
raise HTTPException(status_code=403, detail='本站未开启游客上传,如需上传请先登录后台')
16-
else:
17-
if not is_admin:
18-
raise HTTPException(status_code=401, detail='未授权或授权校验失败')
19-
return is_admin
35+
def verify_token(token: str) -> dict:
36+
"""
37+
验证JWT token
38+
:param token: JWT token
39+
:return: 解码后的数据
40+
"""
41+
try:
42+
header_b64, payload_b64, signature_b64 = token.split('.')
43+
44+
# 验证签名
45+
expected_signature = hmac.new(
46+
settings.jwt_secret_key.encode(),
47+
f"{header_b64}.{payload_b64}".encode(),
48+
'sha256'
49+
).digest()
50+
expected_signature_b64 = base64.b64encode(expected_signature).decode()
51+
52+
if signature_b64 != expected_signature_b64:
53+
raise ValueError("无效的签名")
54+
55+
# 解码payload
56+
payload = json.loads(base64.b64decode(payload_b64))
57+
58+
# 检查是否过期
59+
if payload.get("exp", 0) < time.time():
60+
raise ValueError("token已过期")
61+
62+
return payload
63+
except Exception as e:
64+
raise ValueError(f"token验证失败: {str(e)}")
2065

66+
async def admin_required(authorization: str = Header(default=None), request: Request = None):
67+
"""
68+
验证管理员权限
69+
"""
70+
try:
71+
if not authorization or not authorization.startswith('Bearer '):
72+
raise ValueError("缺少Bearer token")
73+
74+
token = authorization.split(' ')[1]
75+
payload = verify_token(token)
76+
is_admin = payload.get("is_admin", False)
77+
78+
if request.url.path.startswith('/share/'):
79+
if not settings.openUpload and not is_admin:
80+
raise HTTPException(status_code=403, detail='本站未开启游客上传,如需上传请先登录后台')
81+
else:
82+
if not is_admin:
83+
raise HTTPException(status_code=401, detail='未授权或授权校验失败')
84+
return is_admin
85+
except ValueError as e:
86+
raise HTTPException(status_code=401, detail=str(e))
2187

2288
async def get_file_service():
2389
return FileService()

apps/admin/schemas.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,7 @@ class ShareItem(BaseModel):
1313

1414
class DeleteItem(BaseModel):
1515
filename: str
16+
17+
18+
class LoginData(BaseModel):
19+
password: str

apps/admin/views.py

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,30 @@
44
# @Software: PyCharm
55
import datetime
66

7-
from fastapi import APIRouter, Depends
7+
from fastapi import APIRouter, Depends, HTTPException
88
from apps.admin.services import FileService, ConfigService, LocalFileService
99
from apps.admin.dependencies import admin_required, get_file_service, get_config_service, get_local_file_service
10-
from apps.admin.schemas import IDData, ShareItem, DeleteItem
10+
from apps.admin.schemas import IDData, ShareItem, DeleteItem, LoginData
1111
from core.response import APIResponse
1212
from apps.base.models import FileCodes, KeyValue
13+
from apps.admin.dependencies import create_token
14+
from core.settings import settings
1315

1416
admin_api = APIRouter(prefix='/admin', tags=['管理'])
1517

1618

1719
@admin_api.post('/login')
18-
async def login(admin: bool = Depends(admin_required)):
19-
return APIResponse()
20+
async def login(data: LoginData):
21+
# 验证管理员密码
22+
if data.password != settings.admin_password:
23+
raise HTTPException(status_code=401, detail="密码错误")
24+
25+
# 生成包含管理员身份的token
26+
token = create_token({"is_admin": True})
27+
return APIResponse(detail={
28+
"token": token,
29+
"token_type": "Bearer"
30+
})
2031

2132

2233
@admin_api.get('/dashboard')

core/settings.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,9 @@
6666
'port': 12345,
6767
'showAdminAddr': 0,
6868
'robotsText': 'User-agent: *\nDisallow: /',
69+
'jwt_secret_key': "your-secret-key", # 建议使用环境变量
70+
'jwt_algorithm': "HS256",
71+
'admin_password': 'FileCodeBox2023', # 建议使用环境变量存储
6972
}
7073

7174

themes/2024/assets/AdminLayout-DGEvILen.js renamed to themes/2024/assets/AdminLayout-DDemRuZ3.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

themes/2024/assets/DashboardView-6JCRMawe.js renamed to themes/2024/assets/DashboardView-62OQJn6e.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

themes/2024/assets/FileManageView-BYyHY3ZZ.js renamed to themes/2024/assets/FileManageView-pSYIZ4a9.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

themes/2024/assets/LoginView-CUuunog8.js

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

themes/2024/assets/LoginView-Cf0iN_2x.css

Lines changed: 0 additions & 1 deletion
This file was deleted.

themes/2024/assets/LoginView-CvDOmLlY.js

Lines changed: 0 additions & 1 deletion
This file was deleted.

0 commit comments

Comments
 (0)