Skip to content
This repository was archived by the owner on Dec 22, 2024. It is now read-only.

Commit 645618f

Browse files
committedOct 13, 2023
JWT
1 parent 0b0f96f commit 645618f

File tree

10 files changed

+231
-23
lines changed

10 files changed

+231
-23
lines changed
 
-1.31 KB
Binary file not shown.

‎server/main.py

-23
This file was deleted.

‎web/__pycache__/main.cpython-312.pyc

10.6 KB
Binary file not shown.
File renamed without changes.

‎web/api/__init__.py

Whitespace-only changes.

‎web/api/user.py

Whitespace-only changes.

‎web/main.py

+230
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,230 @@
1+
import os
2+
from datetime import datetime, timedelta
3+
from typing import Annotated, Union
4+
5+
from fastapi import Depends, FastAPI, HTTPException, UploadFile, status
6+
from fastapi.responses import FileResponse
7+
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
8+
from jose import JWTError, jwt
9+
from passlib.context import CryptContext
10+
from pydantic import BaseModel
11+
12+
# to get a string like this run:
13+
# openssl rand -hex 32
14+
SECRET_KEY = "09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7"
15+
ALGORITHM = "HS256"
16+
ACCESS_TOKEN_EXPIRE_MINUTES = 30
17+
18+
fake_users_db = {
19+
"johndoe": {
20+
"username": "johndoe",
21+
"full_name": "John Doe",
22+
"email": "johndoe@example.com",
23+
"hashed_password": "$2b$12$EixZaYVK1fsbw1ZfbX3OXePaWxn96p36WQoeG6Lruj3vjPGga31lW",
24+
"disabled": False,
25+
}
26+
}
27+
28+
29+
class Token(BaseModel):
30+
access_token: str
31+
token_type: str
32+
33+
34+
class TokenData(BaseModel):
35+
username: Union[str, None] = None
36+
37+
38+
class User(BaseModel):
39+
username: str
40+
email: Union[str, None] = None
41+
full_name: Union[str, None] = None
42+
disabled: Union[bool, None] = None
43+
44+
45+
class UserInDB(User):
46+
hashed_password: str
47+
48+
49+
class FileInfo(BaseModel):
50+
name: str
51+
size: int
52+
type: str
53+
MD5: str
54+
55+
56+
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
57+
58+
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
59+
60+
# 定义文件系统根目录
61+
root = "./root"
62+
63+
app = FastAPI()
64+
65+
66+
def verify_password(plain_password, hashed_password):
67+
return pwd_context.verify(plain_password, hashed_password)
68+
69+
70+
def get_password_hash(password):
71+
return pwd_context.hash(password)
72+
73+
74+
def get_user(db, username: str):
75+
if username in db:
76+
user_dict = db[username]
77+
return UserInDB(**user_dict)
78+
79+
80+
def authenticate_user(fake_db, username: str, password: str):
81+
user = get_user(fake_db, username)
82+
if not user:
83+
return False
84+
if not verify_password(password, user.hashed_password):
85+
return False
86+
return user
87+
88+
89+
def create_access_token(data: dict, expires_delta: Union[timedelta, None] = None):
90+
to_encode = data.copy()
91+
if expires_delta:
92+
expire = datetime.utcnow() + expires_delta
93+
else:
94+
expire = datetime.utcnow() + timedelta(minutes=15)
95+
to_encode.update({"exp": expire})
96+
encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
97+
return encoded_jwt
98+
99+
100+
async def get_current_user(token: str = Depends(oauth2_scheme)):
101+
credentials_exception = HTTPException(
102+
status_code=status.HTTP_401_UNAUTHORIZED,
103+
detail="Could not validate credentials",
104+
headers={"WWW-Authenticate": "Bearer"},
105+
)
106+
try:
107+
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
108+
username: str = payload.get("sub")
109+
if username is None:
110+
raise credentials_exception
111+
token_data = TokenData(username=username)
112+
except JWTError:
113+
raise credentials_exception
114+
user = get_user(fake_users_db, username=token_data.username)
115+
if user is None:
116+
raise credentials_exception
117+
return user
118+
119+
120+
async def get_current_active_user(current_user: User = Depends(get_current_user)):
121+
if current_user.disabled:
122+
raise HTTPException(status_code=400, detail="Inactive user")
123+
return current_user
124+
125+
126+
@app.post("/token", response_model=Token)
127+
async def login_for_access_token(form_data: OAuth2PasswordRequestForm = Depends()):
128+
user = authenticate_user(fake_users_db, form_data.username, form_data.password)
129+
if not user:
130+
raise HTTPException(
131+
status_code=status.HTTP_401_UNAUTHORIZED,
132+
detail="Incorrect username or password",
133+
headers={"WWW-Authenticate": "Bearer"},
134+
)
135+
access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
136+
access_token = create_access_token(
137+
data={"sub": user.username}, expires_delta=access_token_expires
138+
)
139+
return {"access_token": access_token, "token_type": "bearer"}
140+
141+
142+
@app.get("/users/me/", response_model=User)
143+
async def read_users_me(current_user: User = Depends(get_current_active_user)):
144+
return current_user
145+
146+
147+
@app.get("/users/me/items/")
148+
async def read_own_items(current_user: User = Depends(get_current_active_user)):
149+
return [{"item_id": "Foo", "owner": current_user.username}]
150+
151+
152+
@app.get("/")
153+
def read_root():
154+
return {"Hello": "World"}
155+
156+
157+
@app.post("/api/mkdir/{path:path}")
158+
def mkdir(path: str):
159+
if not os.path.exists(f"{root}/{path}"):
160+
return {"error": "path not exists"}
161+
os.mkdir(f"{root}/{path}")
162+
return {"path": path}
163+
164+
165+
@app.post("/api/move/{path:path}")
166+
def move(path: str):
167+
if not os.path.exists(f"{root}/{path}"):
168+
return {"error": "path not exists"}
169+
os.mkdir(f"{root}/{path}")
170+
return {"path": path}
171+
172+
173+
@app.post("/api/copy/{path:path}")
174+
def copy(path: str):
175+
if not os.path.exists(f"{root}/{path}"):
176+
return {"error": "path not exists"}
177+
os.mkdir(f"{root}/{path}")
178+
return {"path": path}
179+
180+
181+
@app.post("/api/delete/{path:path}")
182+
def delete(path: str):
183+
if not os.path.exists(f"{root}/{path}"):
184+
return {"error": "path not exists"}
185+
os.mkdir(f"{root}/{path}")
186+
return {"path": path}
187+
188+
189+
@app.post("/api/rename/{path:path}")
190+
def rename(path: str):
191+
if not os.path.exists(f"{root}/{path}"):
192+
return {"error": "path not exists"}
193+
os.mkdir(f"{root}/{path}")
194+
return {"path": path}
195+
196+
197+
# 上传文件之前先发送json数据,包括文件名,文件大小,文件类型,文件路径等信息
198+
@app.post("/api/preupload/{path:path}")
199+
def preupload(fileinfo: FileInfo, path: str):
200+
# 判断磁盘空间是否足够,如果不够则返回错误信息
201+
# 判断文件是否已经存在,如果存在则返回错误信息
202+
203+
return {"path": path}
204+
205+
206+
# 上传文件,实现断点续传功能?
207+
@app.post("/api/upload/{path:path}")
208+
async def create_upload_file(file: UploadFile, path: str):
209+
contents = await file.read()
210+
if not os.path.exists(f"{root}/{path}"):
211+
return {"error": "path not exists"}
212+
213+
with open(f"{root}/{path}/{file.filename}", "wb") as f:
214+
f.write(contents)
215+
return {"filename": file.filename}
216+
217+
218+
@app.get("/api/list/{path:path}")
219+
async def list(path: str, token: Annotated[str, Depends(oauth2_scheme)]):
220+
print("token", token)
221+
if not os.path.exists(f"{root}/{path}"):
222+
return {"error": "path not exists"}
223+
return os.listdir(f"{root}/{path}")
224+
225+
226+
@app.get("/api/download/{path:path}")
227+
async def download(path: str):
228+
if not os.path.exists(f"{root}/{path}"):
229+
return {"error": "path not exists"}
230+
return FileResponse(f"{root}/{path}")
File renamed without changes.

‎server/test1.py ‎web/test1.py

File renamed without changes.

‎web/user.py

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# 实现用户登录等功能

0 commit comments

Comments
 (0)