From 12ec678776f199d8dd62b0cd1731fda7863b7b24 Mon Sep 17 00:00:00 2001 From: xsl Date: Mon, 26 Jan 2026 09:39:51 +0800 Subject: [PATCH] =?UTF-8?q?[backend]=20feat:=20=E6=B7=BB=E5=8A=A0=E5=AF=86?= =?UTF-8?q?=E7=A0=81=E5=92=8CJWT=E5=B7=A5=E5=85=B7=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/utils/__init__.py | 9 +++++ .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 349 bytes .../src/utils/__pycache__/jwt.cpython-310.pyc | Bin 0 -> 1104 bytes .../__pycache__/password.cpython-310.pyc | Bin 0 -> 662 bytes backend/src/utils/jwt.py | 33 ++++++++++++++++++ backend/src/utils/password.py | 15 ++++++++ 6 files changed, 57 insertions(+) create mode 100644 backend/src/utils/__init__.py create mode 100644 backend/src/utils/__pycache__/__init__.cpython-310.pyc create mode 100644 backend/src/utils/__pycache__/jwt.cpython-310.pyc create mode 100644 backend/src/utils/__pycache__/password.cpython-310.pyc create mode 100644 backend/src/utils/jwt.py create mode 100644 backend/src/utils/password.py diff --git a/backend/src/utils/__init__.py b/backend/src/utils/__init__.py new file mode 100644 index 00000000..c8209695 --- /dev/null +++ b/backend/src/utils/__init__.py @@ -0,0 +1,9 @@ +from .password import hash_password, verify_password +from .jwt import create_access_token, decode_access_token + +__all__ = [ + "hash_password", + "verify_password", + "create_access_token", + "decode_access_token", +] diff --git a/backend/src/utils/__pycache__/__init__.cpython-310.pyc b/backend/src/utils/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a7d5f6b80b0fb84655fbd55b0b7c9a252d029f59 GIT binary patch literal 349 zcmY+9u};G<5Qc3hX$vBvQlBDHgo!Ju-6R*I8 zJ(R*p_gVkxzw@1~>vNLg{cYEOr1vw6zrm8YP3e~jiYTgyp)ED6Wi)H13sbhGsoIK? z6;Z_tZ6~UHAWii}Q%l2Q-3i~pD7@cWr{d)fUH^3WEhNW6IurpxNQvGSR#MzM$+w}`o&)ql9{{e#L!4b3tF{_%^1*(RFeh_*!F~W>_gz*1 literal 0 HcmV?d00001 diff --git a/backend/src/utils/__pycache__/jwt.cpython-310.pyc b/backend/src/utils/__pycache__/jwt.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8317d975b5ca4cb7018b791bd5ad0a876d2be298 GIT binary patch literal 1104 zcmZ8gJCD>b5Vm6{o6SBr@jjrSO~XpmfIz1Rj>jIlT?C|wLhM_zDFVGz0>>UCe&BS9*X1@7mQg%8Xg7x{+-Sizn=!-G_UJWqL zf=C65A%-)QqY&jd#MszYX5}O#^`2xjw?jL3LZ`NA*2vw^#fZBPQP^Z%=5UWSIN^8^ zF_*X29M)vsBRg!f7H`1`;oc%zqpZz3k7(Fo_5k^NenMvCTiRu@;wsI#ZW_&areYs! zcV(i|vWPR|a`E~w5TX>CjMo)hwntn=k}H)KBiYv!Ld3em?@dy{WmJdIj^Ju4io`N` zc9soqBTFE12&zJxXbWvv6&4+ZH?1vH;X`PH6yDrYMA5O$@U!}~vNj!NRV2k*K$B{W z-O7UdCWyz#GqOP|3Z>EMUI_i|@r!RC-v4;}@#pimUq8J1{^ThDZ{%q)Ra|NUV8L$2 z*{Bq$x}EziO_Opm69%t#rYb4QbpgFY+TE>GA3e9U6buH@aOG0akAfRlmsf-6%5wkO zFc`o$6GNqN>Hxe*O2)M}2$oiZVRR|Dshj66pI=#B9$vWO+rkAe(KN12RYp7B&YVKs zn%gV_y5AtN2yVYl_imRt@7JmR8vD^Bk4g7u_GdQ+8V zvIikfOlEptA~>Ln;w0fxMydoilU^PK`M&w5|5R=ml_r)2 zHMgN!hk(Y`wm1%lKJNS7dJyIV;HcRICS6dt({x-)UMHR-+mn>VS~@zhJ0!yV+ci%3 sFVaM5B9*AAtYiO$&VUd#ME6u)vT4T87?x!h)BHT3HkiaX$IX8T&he-301PSqbc`O2w1T-2Y(19+Z68Kw|-q~O!d*i!R?%d2+@QKxRV@rko zb{1h2<9dzDJ;tqOryMwlPyB+{Y$+CO89}t-3%(K;Vj-52PRK8teN10}`MCamwZ8uF zdwIDbAm!M{G$pv3xT!}^o~N--hRV*X+ILQL>GGoX$vAi8YUUGNDg)Xlpvk9^6-eRb z|0E4xnZ1YL&8uu|raF7)ii~nIqjX*lDr-))st41&%ulq(T*eFs}aBCR8#_r)RKmNas;ZHJIUV~TKhi;q;afwcQ#YM?3fOZo|ct;-IhN1cD7Ql?-4 literal 0 HcmV?d00001 diff --git a/backend/src/utils/jwt.py b/backend/src/utils/jwt.py new file mode 100644 index 00000000..6e04a66d --- /dev/null +++ b/backend/src/utils/jwt.py @@ -0,0 +1,33 @@ +from datetime import datetime, timedelta +from typing import Optional +from jose import JWTError, jwt +from config.settings import get_settings + +settings = get_settings() + + +def create_access_token(data: dict, expires_delta: Optional[timedelta] = None) -> str: + """创建访问令牌""" + to_encode = data.copy() + if expires_delta: + expire = datetime.utcnow() + expires_delta + else: + expire = datetime.utcnow() + timedelta( + minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES + ) + to_encode.update({"exp": expire}) + encoded_jwt = jwt.encode( + to_encode, settings.SECRET_KEY, algorithm=settings.ALGORITHM + ) + return encoded_jwt + + +def decode_access_token(token: str) -> Optional[dict]: + """解码访问令牌""" + try: + payload = jwt.decode( + token, settings.SECRET_KEY, algorithms=[settings.ALGORITHM] + ) + return payload + except JWTError: + return None diff --git a/backend/src/utils/password.py b/backend/src/utils/password.py new file mode 100644 index 00000000..0e5b77a4 --- /dev/null +++ b/backend/src/utils/password.py @@ -0,0 +1,15 @@ +import bcrypt + + +def hash_password(password: str) -> str: + """哈希密码""" + salt = bcrypt.gensalt(rounds=12) + hashed = bcrypt.hashpw(password.encode("utf-8"), salt) + return hashed.decode("utf-8") + + +def verify_password(password: str, hashed_password: str) -> bool: + """验证密码""" + return bcrypt.checkpw( + password.encode("utf-8"), hashed_password.encode("utf-8") + )