Skip to content

Instantly share code, notes, and snippets.

@ChenYFan
Last active March 12, 2021 07:53
Show Gist options
  • Save ChenYFan/1d27c52c81e9cd36df64670532e1d0af to your computer and use it in GitHub Desktop.
Save ChenYFan/1d27c52c81e9cd36df64670532e1d0af to your computer and use it in GitHub Desktop.
CloudFlare无服务器学历验证
/*两个密码子,建议手滚键盘*/
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