JWT -- JSON WEB TOKEN
JWT
https://jwt.io/introduction
是一套开放的标准,定义了在两者之前安全传输信息的方法,信息的内容为JSON格式。
What is JSON Web Token?
JSON Web Token (JWT) is an open standard (RFC 7519) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object. This information can be verified and trusted because it is digitally signed. JWTs can be signed using a secret (with the HMAC algorithm) or a public/private key pair using RSA or ECDSA.
Although JWTs can be encrypted to also provide secrecy between parties, we will focus on signed tokens. Signed tokens can verify the integrity of the claims contained within it, while encrypted tokens hide those claims from other parties. When tokens are signed using public/private key pairs, the signature also certifies that only the party holding the private key is the one that signed it.
两种使用场景:
- 授权
- 信息传输
When should you use JSON Web Tokens?
Here are some scenarios where JSON Web Tokens are useful:
Authorization: This is the most common scenario for using JWT. Once the user is logged in, each subsequent request will include the JWT, allowing the user to access routes, services, and resources that are permitted with that token. Single Sign On is a feature that widely uses JWT nowadays, because of its small overhead and its ability to be easily used across different domains.
Information Exchange: JSON Web Tokens are a good way of securely transmitting information between parties. Because JWTs can be signed—for example, using public/private key pairs—you can be sure the senders are who they say they are. Additionally, as the signature is calculated using the header and the payload, you can also verify that the content hasn't been tampered with.
payload属性名缩写
https://www.iana.org/assignments/jwt/jwt.xhtml
ss Issuer [IESG] [RFC7519, Section 4.1.1] sub Subject [IESG] [RFC7519, Section 4.1.2] aud Audience [IESG] [RFC7519, Section 4.1.3] exp Expiration Time [IESG] [RFC7519, Section 4.1.4] nbf Not Before [IESG] [RFC7519, Section 4.1.5] iat Issued At [IESG] [RFC7519, Section 4.1.6] jti JWT ID [IESG] [RFC7519, Section 4.1.7] name Full name
JWT Authentication in FastAPI
https://www.freecodecamp.org/news/how-to-add-jwt-authentication-in-fastapi/
https://github.com/mabdullahadeel/fcc-fastapi-jwt
登录,生成jwt token,返回给客户端。
from fastapi import FastAPI, status, HTTPException, Depends from fastapi.security import OAuth2PasswordRequestForm from fastapi.responses import RedirectResponse from app.schemas import UserOut, UserAuth, TokenSchema from replit import db from app.utils import ( get_hashed_password, create_access_token, create_refresh_token, verify_password ) from uuid import uuid4 @app.post('/login', summary="Create access and refresh tokens for user", response_model=TokenSchema) async def login(form_data: OAuth2PasswordRequestForm = Depends()): user = db.get(form_data.username, None) if user is None: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail="Incorrect email or password" ) hashed_pass = user['password'] if not verify_password(form_data.password, hashed_pass): raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail="Incorrect email or password" ) return { "access_token": create_access_token(user['email']), "refresh_token": create_refresh_token(user['email']), }
def create_access_token(subject: Union[str, Any], expires_delta: int = None) -> str: if expires_delta is not None: expires_delta = datetime.utcnow() + expires_delta else: expires_delta = datetime.utcnow() + timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES) to_encode = {"exp": expires_delta, "sub": str(subject)} encoded_jwt = jwt.encode(to_encode, JWT_SECRET_KEY, ALGORITHM) return encoded_jwt
权限限制资源,对token进行验证
from app.deps import get_current_user @app.get('/me', summary='Get details of currently logged in user', response_model=UserOut) async def get_me(user: User = Depends(get_current_user)): return user
get user 验证token
from typing import Union, Any from datetime import datetime from fastapi import Depends, HTTPException, status from fastapi.security import OAuth2PasswordBearer from .utils import ( ALGORITHM, JWT_SECRET_KEY ) from jose import jwt from pydantic import ValidationError from app.schemas import TokenPayload, SystemUser from replit import db reuseable_oauth = OAuth2PasswordBearer( tokenUrl="/login", scheme_name="JWT" ) async def get_current_user(token: str = Depends(reuseable_oauth)) -> SystemUser: try: payload = jwt.decode( token, JWT_SECRET_KEY, algorithms=[ALGORITHM] ) token_data = TokenPayload(**payload) if datetime.fromtimestamp(token_data.exp) < datetime.now(): raise HTTPException( status_code = status.HTTP_401_UNAUTHORIZED, detail="Token expired", headers={"WWW-Authenticate": "Bearer"}, ) except(jwt.JWTError, ValidationError): raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail="Could not validate credentials", headers={"WWW-Authenticate": "Bearer"}, ) user: Union[dict[str, Any], None] = db.get(token_data.sub, None) if user is None: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Could not find user", ) return SystemUser(**user)
flowchart compared to cookie
FASTAPI 项目模板也是用JWT
https://github.com/tiangolo/full-stack-fastapi-postgresql/blob/master/%7B%7Bcookiecutter.project_slug%7D%7D/backend/app/app/api/api_v1/endpoints/login.py
@router.post("/login/access-token", response_model=schemas.Token) def login_access_token( db: Session = Depends(deps.get_db), form_data: OAuth2PasswordRequestForm = Depends() ) -> Any: """ OAuth2 compatible token login, get an access token for future requests """ user = crud.user.authenticate( db, email=form_data.username, password=form_data.password ) if not user: raise HTTPException(status_code=400, detail="Incorrect email or password") elif not crud.user.is_active(user): raise HTTPException(status_code=400, detail="Inactive user") access_token_expires = timedelta(minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES) return { "access_token": security.create_access_token( user.id, expires_delta=access_token_expires ), "token_type": "bearer", }
SSO JWT
https://dzone.com/articles/securing-spring-boot-microservices-with-json-web-t
三种角色
token刷新
https://code-maze.com/using-refresh-tokens-in-asp-net-core-authentication/
https://sarwiki.informatik.hu-berlin.de/Zugriffskontrolle_(SSO,JWT,SAML,XACML)
认证授权
auth2认证授权
https://www.yht7.com/news/107169
https://testdriven.io/blog/oauth-python/
在认证服务器上产生token后, 此token在资源服务器上进行校验,校验方式是通过共享的secret完成的, 这里共享是 认证服务器 和 资源服务器。