add simplejwt source code
This commit is contained in:
@@ -0,0 +1,17 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIICwDCCAmagAwIBAgIUHo/UysuMf4+WAcChW3hM1NHDQDkwCgYIKoZIzj0EAwIw
|
||||||
|
gbYxCzAJBgNVBAYTAkNOMQ4wDAYDVQQIDAVBbmh1aTEOMAwGA1UEBwwFSGVmZWkx
|
||||||
|
HjAcBgNVBAoMFVVTVEMgTGludXggVXNlciBHcm91cDEhMB8GA1UECwwYVGhlIEhh
|
||||||
|
Y2tlcmdhbWUgQ29tbWl0dGVlMR0wGwYDVQQDDBRoYWNrLmx1Zy51c3RjLmVkdS5j
|
||||||
|
bjElMCMGCSqGSIb3DQEJARYWaGFja2VyZ2FtZUB1c3RjbHVnLm9yZzAeFw0yMDEw
|
||||||
|
MDgxNTIwMzZaFw0yMTEwMDgxNTIwMzZaMIG2MQswCQYDVQQGEwJDTjEOMAwGA1UE
|
||||||
|
CAwFQW5odWkxDjAMBgNVBAcMBUhlZmVpMR4wHAYDVQQKDBVVU1RDIExpbnV4IFVz
|
||||||
|
ZXIgR3JvdXAxITAfBgNVBAsMGFRoZSBIYWNrZXJnYW1lIENvbW1pdHRlZTEdMBsG
|
||||||
|
A1UEAwwUaGFjay5sdWcudXN0Yy5lZHUuY24xJTAjBgkqhkiG9w0BCQEWFmhhY2tl
|
||||||
|
cmdhbWVAdXN0Y2x1Zy5vcmcwVjAQBgcqhkjOPQIBBgUrgQQACgNCAAQcAwLQKJf1
|
||||||
|
W8podrvryfX7GI3xEneVlEriKNh7ltLe35BfU405TSKVXOKZfxdukiUwKZUPOI4o
|
||||||
|
zqsAfklnl/Jco1MwUTAdBgNVHQ4EFgQUnHTMWSWk9BgfVDphGi/VhTH5zOYwHwYD
|
||||||
|
VR0jBBgwFoAUnHTMWSWk9BgfVDphGi/VhTH5zOYwDwYDVR0TAQH/BAUwAwEB/zAK
|
||||||
|
BggqhkjOPQQDAgNIADBFAiAtkdkJ6vO1abjJt5jCnRDHCnGHTPetOtAQ12Fr1fo1
|
||||||
|
eQIhAO4T9HjFgSAP5Bg/bzeTS5jGvZAnN14e2sjllR6392J8
|
||||||
|
-----END CERTIFICATE-----
|
||||||
@@ -0,0 +1,97 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>普通的身份认证器</title>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<link rel="stylesheet" href="static/user.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<noscript>
|
||||||
|
Although not necessary...
|
||||||
|
It's recommended to enable JavaScript to solve this problem.
|
||||||
|
</noscript>
|
||||||
|
<div id="app">
|
||||||
|
<input v-model.trim="token" placeholder="在这里输入比赛 token...">
|
||||||
|
<button @click='login'>以 Guest 登录</button>
|
||||||
|
<button @click='getProfile'>获取用户信息</button>
|
||||||
|
<div class="text-block">
|
||||||
|
<p>{{ message }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- Powered by FastAPI, Axios and Vue.js -->
|
||||||
|
<script src="static/axios.min.js"></script>
|
||||||
|
<script src="static/vue.js"></script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
var app = new Vue({
|
||||||
|
el: '#app',
|
||||||
|
data: {
|
||||||
|
message: '请点击登录...',
|
||||||
|
jwt: null,
|
||||||
|
token: null,
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
login: function () {
|
||||||
|
if (this.token) {
|
||||||
|
axios.post('/token', null, {
|
||||||
|
headers: {
|
||||||
|
"Hg-Token": this.token
|
||||||
|
}
|
||||||
|
}).then(
|
||||||
|
response => {
|
||||||
|
this.jwt = response.data.access_token
|
||||||
|
this.message = '登录成功。'
|
||||||
|
}
|
||||||
|
).catch(
|
||||||
|
error => {
|
||||||
|
this.message = this.errorOutput(error);
|
||||||
|
}
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
this.message = '请输入你的比赛 token。';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getProfile: function () {
|
||||||
|
if (!this.jwt) {
|
||||||
|
this.message = '请先登录。';
|
||||||
|
}
|
||||||
|
else if (this.token) {
|
||||||
|
axios.get('/profile', {
|
||||||
|
headers: {
|
||||||
|
Authorization: 'Bearer ' + this.jwt,
|
||||||
|
"Hg-Token": this.token
|
||||||
|
}
|
||||||
|
}).then(
|
||||||
|
response => {
|
||||||
|
this.message = response.data;
|
||||||
|
}
|
||||||
|
).catch(
|
||||||
|
error => {
|
||||||
|
this.message = this.errorOutput(error);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
this.message = '请输入你的比赛 token。';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
errorOutput: function (error) {
|
||||||
|
if (error.response) {
|
||||||
|
return error.response.data.detail + "(" + error.response.status + ")";
|
||||||
|
} else if (error.request) {
|
||||||
|
return "未能连接到后端服务器。";
|
||||||
|
} else {
|
||||||
|
return "未知错误: " + error.message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted: function () {
|
||||||
|
const token = new URLSearchParams(window.location.search).get("token");
|
||||||
|
window.history.replaceState({}, null, '/');
|
||||||
|
if (token) {
|
||||||
|
this.token = token;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
-----BEGIN RSA PRIVATE KEY-----
|
||||||
|
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
|
||||||
|
-----END RSA PRIVATE KEY-----
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
-----BEGIN RSA PUBLIC KEY-----
|
||||||
|
MIICCgKCAgEAn/KiHQ+/zwE7kY/Xf89PY6SowSb7CUk2b+lSVqC9u+R4BaE/5tNF
|
||||||
|
eNlneGNny6fQhCRA+Pdw1UJSnNpG26z/uOK8+H7fMb2Da5t/94wavw410sCKVbvf
|
||||||
|
ft8gKquUaeq//tp20BETeS5MWIXp5EXCE+lEdAHgmWWoMVMIOXwaKTMnCVGJ2SRr
|
||||||
|
+xH9147FZqOa/17PYIIHuUDlfeGi+Iu7T6a+QZ0tvmHL6j9Onk/EEONuUDfElonY
|
||||||
|
M688jhuAM/FSLfMzdyk23mJk3CKPah48nzVmb1YRyfBWiVFGYQqMCBnWgoGOanpd
|
||||||
|
46Fp1ff1zBn4sZTfPSOus/+00D5Lxh6bsbRa6A1vAApfmTcu026lIb7gbG7DU1/s
|
||||||
|
eDId9s1qA5BJpzWFKO4ztkPGvPTUok8hQBMDaSH1JOoFQgfJIfC7w2CQe+KbodQL
|
||||||
|
3akKQDCZhcoA4tf5VC6ODJpFxCn6blML5cD6veOBPJiIk8DBRgmt2AHzOUju+5ns
|
||||||
|
QcplOVxW5TFYxLqeJ8FPWqQcVekZ749FjchtAwPlUsoWIH0PTSun38ua8usrwTXb
|
||||||
|
pBlf4r0wz22FPqaecvp7z6Rj/xfDauDGDSU4hmn/TY9Fr+OmFJPW/9k2RAv7KEFv
|
||||||
|
FCLP/3U3r0FMwSe/FPHmt5fjAtsGlZLj+bZsgwFllYeD90VQU8Ds+KkCAwEAAQ==
|
||||||
|
-----END RSA PUBLIC KEY-----
|
||||||
@@ -0,0 +1,178 @@
|
|||||||
|
from datetime import datetime, timedelta
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
from fastapi import Depends, FastAPI, HTTPException, status, Header, Request
|
||||||
|
from fastapi.security import OAuth2PasswordBearer
|
||||||
|
from fastapi.responses import FileResponse
|
||||||
|
from fastapi.staticfiles import StaticFiles
|
||||||
|
import jwt
|
||||||
|
from pydantic import BaseModel
|
||||||
|
from hashlib import sha256
|
||||||
|
import logging
|
||||||
|
from fastapi.logger import logger as fastapi_logger
|
||||||
|
|
||||||
|
import OpenSSL
|
||||||
|
import base64
|
||||||
|
|
||||||
|
|
||||||
|
ACCESS_TOKEN_EXPIRE_MINUTES = 30
|
||||||
|
PUBLIC_KEY = open("jwt.key.pub", "r").read()
|
||||||
|
PRIVATE_KEY = open("jwt.key", "r").read()
|
||||||
|
SALT = b'd_Yn2xWvnu'
|
||||||
|
|
||||||
|
|
||||||
|
users_db = {
|
||||||
|
"admin": {
|
||||||
|
"username": "admin",
|
||||||
|
"flag": "flag{just_A_simple_Json_Web_T0ken_exp1oit_",
|
||||||
|
"disabled": False,
|
||||||
|
},
|
||||||
|
"guest": {
|
||||||
|
"username": "guest",
|
||||||
|
"flag": "只有 'admin' 用户才有 flag 哦!",
|
||||||
|
"disabled": False,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
with open("cert.pem") as f:
|
||||||
|
cert = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, f.read())
|
||||||
|
|
||||||
|
|
||||||
|
class Token(BaseModel):
|
||||||
|
access_token: str
|
||||||
|
token_type: str
|
||||||
|
|
||||||
|
|
||||||
|
class TokenData(BaseModel):
|
||||||
|
username: Optional[str] = None
|
||||||
|
|
||||||
|
|
||||||
|
class User(BaseModel):
|
||||||
|
username: str
|
||||||
|
disabled: Optional[bool] = None
|
||||||
|
|
||||||
|
|
||||||
|
class UserInDB(User):
|
||||||
|
flag: str
|
||||||
|
|
||||||
|
|
||||||
|
class TokenOption(BaseModel):
|
||||||
|
hg_token: str
|
||||||
|
|
||||||
|
|
||||||
|
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
|
||||||
|
|
||||||
|
app = FastAPI()
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
app.mount("/static", StaticFiles(directory="static"), name="static")
|
||||||
|
|
||||||
|
|
||||||
|
def get_user(db, username: str):
|
||||||
|
if username in db:
|
||||||
|
user_dict = db[username]
|
||||||
|
return UserInDB(**user_dict)
|
||||||
|
|
||||||
|
|
||||||
|
def authenticate_user(db, username: str, password: str):
|
||||||
|
user = get_user(db, username)
|
||||||
|
if not user:
|
||||||
|
return False
|
||||||
|
if username != "guest":
|
||||||
|
return False
|
||||||
|
return user
|
||||||
|
|
||||||
|
|
||||||
|
def create_access_token(data: dict, expires_delta: Optional[timedelta] = None):
|
||||||
|
to_encode = data.copy()
|
||||||
|
if expires_delta:
|
||||||
|
expire = datetime.utcnow() + expires_delta
|
||||||
|
else:
|
||||||
|
expire = datetime.utcnow() + timedelta(minutes=15)
|
||||||
|
to_encode.update({"exp": expire})
|
||||||
|
encoded_jwt = jwt.encode(to_encode, PRIVATE_KEY, algorithm="RS256")
|
||||||
|
return encoded_jwt
|
||||||
|
|
||||||
|
|
||||||
|
def check_hackergame_token(hg_token):
|
||||||
|
raise_error = False
|
||||||
|
if hg_token is None:
|
||||||
|
raise_error = True
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
id, sig = hg_token.split(":", 1)
|
||||||
|
sig = base64.b64decode(sig, validate=True)
|
||||||
|
OpenSSL.crypto.verify(cert, sig, id.encode(), "sha256")
|
||||||
|
except Exception as e:
|
||||||
|
raise_error = True
|
||||||
|
if raise_error:
|
||||||
|
raise HTTPException(status_code=403, detail="比赛 token 校验错误。\n如果您正在使用网页完成此题目,请从比赛平台打开题目(推荐),或正确输入比赛 token。\n如果您正在使用非网页方式请求后端,请确认 HTTP 请求头 hg-token 设置正确。")
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
async def get_current_user(token: str = Depends(oauth2_scheme)):
|
||||||
|
credentials_exception = HTTPException(
|
||||||
|
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||||
|
detail="Could not validate credentials",
|
||||||
|
headers={"WWW-Authenticate": "Bearer"},
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
payload = jwt.decode(token, PUBLIC_KEY)
|
||||||
|
username: str = payload.get("sub")
|
||||||
|
if username is None:
|
||||||
|
raise credentials_exception
|
||||||
|
token_data = TokenData(username=username)
|
||||||
|
except:
|
||||||
|
raise credentials_exception
|
||||||
|
user = get_user(users_db, username=token_data.username)
|
||||||
|
if user is None:
|
||||||
|
raise credentials_exception
|
||||||
|
return user
|
||||||
|
|
||||||
|
|
||||||
|
async def get_current_active_user(current_user: User = Depends(get_current_user)):
|
||||||
|
if current_user.disabled:
|
||||||
|
raise HTTPException(status_code=400, detail="Inactive user")
|
||||||
|
return current_user
|
||||||
|
|
||||||
|
|
||||||
|
@app.post("/token", response_model=Token)
|
||||||
|
async def login_for_access_token(hg_token: Optional[str] = Header(None)):
|
||||||
|
check_hackergame_token(hg_token)
|
||||||
|
access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
|
||||||
|
access_token = create_access_token(
|
||||||
|
data={"sub": "guest"}, expires_delta=access_token_expires
|
||||||
|
)
|
||||||
|
return {"access_token": access_token, "token_type": "bearer"}
|
||||||
|
|
||||||
|
|
||||||
|
@app.get("/profile", response_model=UserInDB)
|
||||||
|
async def read_users_me(raw: Request,
|
||||||
|
current_user: User = Depends(get_current_active_user),
|
||||||
|
hg_token: Optional[str] = Header(None)):
|
||||||
|
check_hackergame_token(hg_token)
|
||||||
|
if current_user.username == 'admin':
|
||||||
|
# format flag
|
||||||
|
user = current_user.copy()
|
||||||
|
user.flag = user.flag + \
|
||||||
|
sha256(SALT + hg_token.encode('utf-8')).hexdigest()[:6] + '}'
|
||||||
|
# log user data for future analysis
|
||||||
|
fastapi_logger.warn(f"User with token {hg_token[:10]} gets flag with jwt {raw.headers['authorization']}")
|
||||||
|
else:
|
||||||
|
user = current_user
|
||||||
|
return user
|
||||||
|
|
||||||
|
|
||||||
|
@app.get("/")
|
||||||
|
def index():
|
||||||
|
return FileResponse('index.html', media_type='text/html')
|
||||||
|
|
||||||
|
|
||||||
|
@app.post("/debug")
|
||||||
|
async def debug():
|
||||||
|
return {
|
||||||
|
"ACCESS_TOKEN_EXPIRE_MINUTES": ACCESS_TOKEN_EXPIRE_MINUTES,
|
||||||
|
"PUBLIC_KEY": PUBLIC_KEY
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
fastapi==0.61.0
|
||||||
|
uvicorn==0.11.8
|
||||||
|
PyJWT==1.5.0 # intentionally here!
|
||||||
|
cryptography==3.1.1
|
||||||
|
aiofiles==0.5.0
|
||||||
|
pyOpenSSL==19.1.0 # dynamic flag check
|
||||||
+3
File diff suppressed because one or more lines are too long
@@ -0,0 +1,3 @@
|
|||||||
|
.text-block {
|
||||||
|
white-space: pre;
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user