Last active
March 12, 2021 07:53
-
-
Save ChenYFan/1d27c52c81e9cd36df64670532e1d0af to your computer and use it in GitHub Desktop.
CloudFlare无服务器学历验证
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*两个密码子,建议手滚键盘*/ | |
const privatek = "" | |
const privatepass = "" | |
/*前端处理区域,将征用三个目录*/ | |
if (rp(path) == "/getaccesstoken" || rp(path) == "/getcap" || rp(path) == '/getcapimg') { | |
try { await JSON.parse(Decrypt(urlObj.searchParams.get('refreshtoken'), privatek)) } catch (e) { return returnc(0) } | |
const RToken = urlObj.searchParams.get('refreshtoken') | |
const _RT = await JSON.parse(Decrypt(RToken, privatek)) | |
if (checktime(_RT)) { | |
if (await checkban(RToken, privatek)) { | |
const capi = await JSON.parse(await (await fetch('https://raw.githubusercontent.com/HexoPlusPlus/Captcha-IMG/master/cap.json')).text()) | |
if (rp(path) == "/getaccesstoken") { | |
if (urlObj.searchParams.get('recapq') != undefined && urlObj.searchParams.get('recapans') != undefined) { | |
try { await JSON.parse(Decrypt(urlObj.searchParams.get('recapq'), privatek)) } catch (e) { return returnc(4) } | |
const reqa = await JSON.parse(Decrypt(urlObj.searchParams.get('recapq'), privatek)) | |
if (checkcap(reqa, urlObj.searchParams.get('recapans'), RToken, capi)) { | |
const _AccessToken = { | |
date: (new Date()).valueOf(), | |
salt: salt(), | |
RefreshToken: RToken, | |
privatepass: privatepass | |
} | |
const AT = Encrypt(await JSON.stringify(_AccessToken), privatek) | |
return new Response(AT) | |
} else { return returnc(5) } | |
} else { | |
return returnc(3) | |
} | |
} | |
if (rp(path) == "/getcap") { | |
const id = randomNum(0, 10185) | |
let _CAP = { | |
RefreshToken: RToken, | |
capque: capi[id][1], | |
capans: capi[id][2], | |
capid: id, | |
salt: salt() | |
} | |
console.log(capi[id][2]) | |
const recapq = Encrypt(await JSON.stringify(_CAP), privatek) | |
return new Response(recapq) | |
} | |
if (rp(path) == "/getcapimg") { | |
if (urlObj.searchParams.get('recapq') != undefined) { | |
try { await JSON.parse(Decrypt(urlObj.searchParams.get('recapq'), privatek)) } catch (e) { return returnc(4) } | |
const _CAP = await JSON.parse(Decrypt(urlObj.searchParams.get('recapq'), privatek)) | |
return fetch(`https://raw.githubusercontent.com/HexoPlusPlus/Captcha-IMG/master/img/${_CAP["capque"]}.gif`) | |
} else { return returnc(6) } | |
} | |
} else { return returnc(2) } | |
} else { return returnc(1) } | |
} | |
//if(await checkAT(urlObj.searchParams.get('token'),true)){} | |
//上述代码表示在有效期内AccessToken永久有效 | |
//if(await checkAT(urlObj.searchParams.get('token'),false)){} | |
//上述代码表示AccessToken在使用一次后就吊销 | |
//吊销机制是:AT与CapID联系,CapID与RefreshToken联系 | |
//checkAT将在第一次校验RT成功后将其吊销,第二个参数实际上代表了是否校验RT吊销 | |
/*以下是代码核心区*/ | |
async function checkAT(AT, check) { | |
checkRT = check | |
const RefreshToken = await JSON.parse(Decrypt(AT, privatek)) | |
let RToken = RefreshToken["RefreshToken"] | |
const date = RefreshToken["date"] | |
const now = (new Date()).valueOf() | |
if (RefreshToken["privatepass"] == privatepass && now - 10 * 60000 < date && now + 10 * 60000 > date) { | |
if ((checktime(await JSON.parse(Decrypt(RToken, privatek))) && await checkban(RToken)) || checkRT) { | |
let banlist = await JSON.parse(await KVNAME.get("_banrt")) || [] | |
if (!banlist.includes(RToken)) { | |
banlist.push(RToken) | |
await KVNAME.put("_banrt", await JSON.stringify(banlist), { expirationTtl: 5 * 60 }) | |
} | |
return true | |
} else { console.log("吊销的RT"); return false } | |
} else { console.log("过期的AT"); return false } | |
} | |
function checkcap(q, ans, RToken, capi) { | |
if (capi[q["capid"]][2] == ans && RToken == q["RefreshToken"]) return true | |
return false | |
} | |
function getJsonLength(jsonData) { | |
var jsonLength = 0; | |
for (var item in jsonData) { | |
jsonLength++; | |
} | |
return jsonLength; | |
} | |
function returnc(i) { | |
const code = [ | |
"RefreshToken校验错误", | |
"RefreshToken过期", | |
"RefreshToken已失效", | |
"Capthca需要校验", | |
"Capthca校验错误", | |
"Capthca答案错误", | |
"CapthcaID丢失", | |
"AccessToken校验失败" | |
] | |
const as = { | |
code: i, | |
msg: code[i] || "未知错误,请联系管理员" | |
} | |
const ans = JSON.stringify(as) | |
return new Response(ans, { headers: { "content-type": "application/json" } }) | |
} | |
function checktime(RT) { | |
const date = RT["date"] | |
const now = (new Date()).valueOf() | |
if (now - 5 * 60000 < date && now + 5 * 60000 > date) { return true } | |
return false | |
return true | |
} | |
async function checkban(RT) { | |
const r = await JSON.parse(await KVNAME.get("_banrt")) || [] | |
if(r.includes(RT)){return false} | |
return true | |
} | |
function salt() { | |
var str = "abcdefghijklmnopqrstuvwxyz0123456789"; | |
var result = ""; | |
for (var i = 0; i < 24; i++) { | |
result += str[parseInt(Math.random() * str.length)]; | |
} | |
return result; | |
} | |
function randomNum(minNum, maxNum) { | |
switch (arguments.length) { | |
case 1: | |
return parseInt(Math.random() * minNum + 1, 10); | |
break; | |
case 2: | |
return parseInt(Math.random() * (maxNum - minNum + 1) + minNum, 10); | |
break; | |
default: | |
return 0; | |
break; | |
} | |
} | |
function rp(path) { | |
return path.split('?')[0] | |
} | |
function Encrypt(str, pwd) { | |
if (str == "") return ""; | |
str = escape(str); | |
if (!pwd || pwd == "") { var pwd = "1234"; } | |
pwd = escape(pwd); | |
if (pwd == null || pwd.length <= 0) { | |
console.log("Please enter a password with which to encrypt the message."); | |
return null; | |
} | |
var prand = ""; | |
for (var I = 0; I < pwd.length; I++) { | |
prand += pwd.charCodeAt(I).toString(); | |
} | |
var sPos = Math.floor(prand.length / 5); | |
var mult = parseInt(prand.charAt(sPos) + prand.charAt(sPos * 2) + prand.charAt(sPos * 3) + prand.charAt(sPos * 4) + prand.charAt(sPos * 5)); | |
var incr = Math.ceil(pwd.length / 2); | |
var modu = Math.pow(2, 31) - 1; | |
if (mult < 2) { | |
console.log("Algorithm cannot find a suitable hash. Please choose a different password. \nPossible considerations are to choose a more complex or longer password."); | |
return null; | |
} | |
var salt = Math.round(Math.random() * 1000000000) % 100000000; | |
prand += salt; | |
while (prand.length > 10) { | |
prand = (parseInt(prand.substring(0, 10)) + parseInt(prand.substring(10, prand.length))).toString(); | |
} | |
prand = (mult * prand + incr) % modu; | |
var enc_chr = ""; | |
var enc_str = ""; | |
for (var I = 0; I < str.length; I++) { | |
enc_chr = parseInt(str.charCodeAt(I) ^ Math.floor((prand / modu) * 255)); | |
if (enc_chr < 16) { | |
enc_str += "0" + enc_chr.toString(16); | |
} else | |
enc_str += enc_chr.toString(16); | |
prand = (mult * prand + incr) % modu; | |
} | |
salt = salt.toString(16); | |
while (salt.length < 8) salt = "0" + salt; | |
enc_str += salt; | |
return enc_str; | |
} | |
function Decrypt(str, pwd) { | |
if (str == "") return ""; | |
if (!pwd || pwd == "") { var pwd = "1234"; } | |
pwd = escape(pwd); | |
if (str == null || str.length < 8) { | |
console.log("A salt value could not be extracted from the encrypted message because it's length is too short. The message cannot be decrypted."); | |
return; | |
} | |
if (pwd == null || pwd.length <= 0) { | |
console.log("Please enter a password with which to decrypt the message."); | |
return; | |
} | |
var prand = ""; | |
for (var I = 0; I < pwd.length; I++) { | |
prand += pwd.charCodeAt(I).toString(); | |
} | |
var sPos = Math.floor(prand.length / 5); | |
var mult = parseInt(prand.charAt(sPos) + prand.charAt(sPos * 2) + prand.charAt(sPos * 3) + prand.charAt(sPos * 4) + prand.charAt(sPos * 5)); | |
var incr = Math.round(pwd.length / 2); | |
var modu = Math.pow(2, 31) - 1; | |
var salt = parseInt(str.substring(str.length - 8, str.length), 16); | |
str = str.substring(0, str.length - 8); | |
prand += salt; | |
while (prand.length > 10) { | |
prand = (parseInt(prand.substring(0, 10)) + parseInt(prand.substring(10, prand.length))).toString(); | |
} | |
prand = (mult * prand + incr) % modu; | |
var enc_chr = ""; | |
var enc_str = ""; | |
for (var I = 0; I < str.length; I += 2) { | |
enc_chr = parseInt(parseInt(str.substring(I, I + 2), 16) ^ Math.floor((prand / modu) * 255)); | |
enc_str += String.fromCharCode(enc_chr); | |
prand = (mult * prand + incr) % modu; | |
} | |
return unescape(enc_str); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment