55from datetime import datetime , timedelta
66from typing import Optional
77
8- from fastapi import APIRouter
9- from fastapi import Depends , HTTPException , status
8+ from fastapi import APIRouter , Depends , HTTPException , status
109from fastapi .security import OAuth2PasswordBearer , OAuth2PasswordRequestForm
1110from jose import JWTError , jwt
1211from passlib .context import CryptContext
1514app06 = APIRouter ()
1615
1716"""OAuth2 密码模式和 FastAPI 的 OAuth2PasswordBearer"""
18- oauth2_scheme = OAuth2PasswordBearer (tokenUrl = "chapter06/token" ) # 请求Token的URL地址 http://127.0.0.1:8000/chapter06/token
17+
18+ """
19+ OAuth2PasswordBearer是接收URL作为参数的一个类:客户端会向该URL发送username和password参数,然后得到一个Token值
20+ OAuth2PasswordBearer并不会创建相应的URL路径操作,只是指明客户端用来请求Token的URL地址
21+ 当请求到来的时候,FastAPI会检查请求的Authorization头信息,如果没有找到Authorization头信息,或者头信息的内容不是Bearer token,它会返回401状态码(UNAUTHORIZED)
22+ """
23+
24+ oauth2_schema = OAuth2PasswordBearer (tokenUrl = "/chapter06/token" ) # 请求Token的URL地址 http://127.0.0.1:8000/chapter06/token
1925
2026
2127@app06 .get ("/oauth2_password_bearer" )
22- async def oauth2_password_bearer (token : str = Depends (oauth2_scheme )):
28+ async def oauth2_password_bearer (token : str = Depends (oauth2_schema )):
2329 return {"token" : token }
2430
2531
26- """基于 Password 和 Bearer token 的 OAuth2 认证 """
32+ """基于 Password 和 Bearer token 的 OAuth2 认证"""
2733
2834fake_users_db = {
2935 "john snow" : {
@@ -58,18 +64,30 @@ class UserInDB(User):
5864 hashed_password : str
5965
6066
67+ @app06 .post ("/token" )
68+ async def login (form_data : OAuth2PasswordRequestForm = Depends ()):
69+ user_dict = fake_users_db .get (form_data .username )
70+ if not user_dict :
71+ raise HTTPException (status_code = status .HTTP_400_BAD_REQUEST , detail = "Incorrect username or password" )
72+ user = UserInDB (** user_dict )
73+ hashed_password = fake_hash_password (form_data .password )
74+ if not hashed_password == user .hashed_password :
75+ raise HTTPException (status_code = status .HTTP_400_BAD_REQUEST , detail = "Incorrect username or password" )
76+ return {"access_token" : user .username , "token_type" : "bearer" }
77+
78+
6179def get_user (db , username : str ):
6280 if username in db :
6381 user_dict = db [username ]
6482 return UserInDB (** user_dict )
6583
6684
67- def fake_decode_token (token ):
85+ def fake_decode_token (token : str ):
6886 user = get_user (fake_users_db , token )
6987 return user
7088
7189
72- async def get_current_user (token : str = Depends (oauth2_scheme )):
90+ async def get_current_user (token : str = Depends (oauth2_schema )):
7391 user = fake_decode_token (token )
7492 if not user :
7593 raise HTTPException (
@@ -82,23 +100,10 @@ async def get_current_user(token: str = Depends(oauth2_scheme)):
82100
83101async def get_current_active_user (current_user : User = Depends (get_current_user )):
84102 if current_user .disabled :
85- raise HTTPException (status_code = 400 , detail = "Inactive user" )
103+ raise HTTPException (status_code = status . HTTP_400_BAD_REQUEST , detail = "Inactive user" )
86104 return current_user
87105
88106
89- @app06 .post ("/token" )
90- async def login (form_data : OAuth2PasswordRequestForm = Depends ()):
91- user_dict = fake_users_db .get (form_data .username )
92- if not user_dict :
93- raise HTTPException (status_code = 400 , detail = "Incorrect username or password" )
94- user = UserInDB (** user_dict )
95- hashed_password = fake_hash_password (form_data .password )
96- if not hashed_password == user .hashed_password :
97- raise HTTPException (status_code = 400 , detail = "Incorrect username or password" )
98-
99- return {"access_token" : user .username , "token_type" : "bearer" }
100-
101-
102107@app06 .get ("/users/me" )
103108async def read_users_me (current_user : User = Depends (get_current_active_user )):
104109 return current_user
@@ -116,44 +121,38 @@ async def read_users_me(current_user: User = Depends(get_current_active_user)):
116121 }
117122})
118123
119- SECRET_KEY = "09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7"
120- ALGORITHM = "HS256"
121- ACCESS_TOKEN_EXPIRE_MINUTES = 30
124+ SECRET_KEY = "09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7" # 生成密钥 openssl rand -hex 32
125+ ALGORITHM = "HS256" # 算法
126+ ACCESS_TOKEN_EXPIRE_MINUTES = 30 # 访问令牌过期分钟
122127
123128
124129class Token (BaseModel ):
130+ """返回给用户的Token"""
125131 access_token : str
126132 token_type : str
127133
128134
129- class TokenData (BaseModel ):
130- username : Optional [str ] = None
131-
132-
133135pwd_context = CryptContext (schemes = ["bcrypt" ], deprecated = "auto" )
134136
135- oauth2_scheme = OAuth2PasswordBearer (tokenUrl = "chapter06/jwt/token" )
137+ oauth2_schema = OAuth2PasswordBearer (tokenUrl = "/ chapter06/jwt/token" )
136138
137139
138- def verify_password (plain_password , hashed_password ):
140+ def verity_password (plain_password : str , hashed_password : str ):
141+ """对密码进行校验"""
139142 return pwd_context .verify (plain_password , hashed_password )
140143
141144
142- def get_password_hash (password ):
143- return pwd_context .hash (password )
144-
145-
146145def jwt_get_user (db , username : str ):
147146 if username in db :
148147 user_dict = db [username ]
149148 return UserInDB (** user_dict )
150149
151150
152- def authenticate_user ( fake_db , username : str , password : str ):
153- user = get_user ( fake_db , username )
151+ def jwt_authenticate_user ( db , username : str , password : str ):
152+ user = jwt_get_user ( db = db , username = username )
154153 if not user :
155154 return False
156- if not verify_password ( password , user .hashed_password ):
155+ if not verity_password ( plain_password = password , hashed_password = user .hashed_password ):
157156 return False
158157 return user
159158
@@ -165,57 +164,51 @@ def create_access_token(data: dict, expires_delta: Optional[timedelta] = None):
165164 else :
166165 expire = datetime .utcnow () + timedelta (minutes = 15 )
167166 to_encode .update ({"exp" : expire })
168- encoded_jwt = jwt .encode (to_encode , SECRET_KEY , algorithm = ALGORITHM )
167+ encoded_jwt = jwt .encode (claims = to_encode , key = SECRET_KEY , algorithm = ALGORITHM )
169168 return encoded_jwt
170169
171170
172- async def jwt_get_current_user (token : str = Depends (oauth2_scheme )):
171+ @app06 .post ("/jwt/token" , response_model = Token )
172+ async def login_for_access_token (form_data : OAuth2PasswordRequestForm = Depends ()):
173+ user = jwt_authenticate_user (db = fake_users_db , username = form_data .username , password = form_data .password )
174+ if not user :
175+ raise HTTPException (
176+ status .HTTP_401_UNAUTHORIZED ,
177+ detail = "Incorrect username or password" ,
178+ headers = {"WWW-Authenticate" : "Bearer" },
179+ )
180+ access_token_expires = timedelta (minutes = ACCESS_TOKEN_EXPIRE_MINUTES )
181+ access_token = create_access_token (
182+ data = {"sub" : user .username }, expires_delta = access_token_expires
183+ )
184+ return {"access_token" : access_token , "token_type" : "bearer" }
185+
186+
187+ async def jwt_get_current_user (token : str = Depends (oauth2_schema )):
173188 credentials_exception = HTTPException (
174- status_code = status .HTTP_401_UNAUTHORIZED ,
189+ status .HTTP_401_UNAUTHORIZED ,
175190 detail = "Could not validate credentials" ,
176191 headers = {"WWW-Authenticate" : "Bearer" },
177192 )
178193 try :
179- payload = jwt .decode (token , SECRET_KEY , algorithms = [ALGORITHM ])
180- username : str = payload .get ("sub" )
194+ payload = jwt .decode (token = token , key = SECRET_KEY , algorithms = [ALGORITHM ])
195+ username = payload .get ("sub" )
181196 if username is None :
182197 raise credentials_exception
183- token_data = TokenData (username = username )
184198 except JWTError :
185199 raise credentials_exception
186- user = get_user ( fake_users_db , username = token_data . username )
200+ user = jwt_get_user ( db = fake_users_db , username = username )
187201 if user is None :
188202 raise credentials_exception
189203 return user
190204
191205
192206async def jwt_get_current_active_user (current_user : User = Depends (jwt_get_current_user )):
193207 if current_user .disabled :
194- raise HTTPException (status_code = 400 , detail = "Inactive user" )
208+ raise HTTPException (status_code = status . HTTP_400_BAD_REQUEST , detail = "Inactive user" )
195209 return current_user
196210
197211
198- @app06 .post ("/jwt/token" , response_model = Token )
199- async def login_for_access_token (form_data : OAuth2PasswordRequestForm = Depends ()):
200- user = authenticate_user (fake_users_db , form_data .username , form_data .password )
201- if not user :
202- raise HTTPException (
203- status_code = status .HTTP_401_UNAUTHORIZED ,
204- detail = "Incorrect username or password" ,
205- headers = {"WWW-Authenticate" : "Bearer" },
206- )
207- access_token_expires = timedelta (minutes = ACCESS_TOKEN_EXPIRE_MINUTES )
208- access_token = create_access_token (
209- data = {"sub" : user .username }, expires_delta = access_token_expires
210- )
211- return {"access_token" : access_token , "token_type" : "bearer" }
212-
213-
214- @app06 .get ("/jwt/users/me/" , response_model = User )
215- async def read_users_me (current_user : User = Depends (jwt_get_current_active_user )):
212+ @app06 .get ("/jwt/users/me" )
213+ async def jwt_read_users_me (current_user : User = Depends (jwt_get_current_active_user )):
216214 return current_user
217-
218-
219- @app06 .get ("/jwt/users/me/items/" )
220- async def read_own_items (current_user : User = Depends (jwt_get_current_active_user )):
221- return [{"item_id" : "Foo" , "owner" : current_user .username }]
0 commit comments