WisW 发表于 前天 22:56

新的正版验证可行性分析?

本帖最后由 WisW 于 2025-1-28 23:04 编辑

瞎写的;

我承认, 我一直对拿一个真正能登上游戏账号的token来验证正版持不满意的态度
这意味着我的账号访问权限被放出去了24个小时(我承认比原先的不改密码就是永远好)

好的, 新的正版验证是基于皮肤的验证, 流程如下: 请求论坛 -> 论坛返回一个随机皮肤 -> 玩家更改皮肤 -> 论坛验证 -> 完成
这个服务应该压力不会太大: 需要发几个请求, 要有数据库; (我突然想到一个, 我们能不能用签名来干掉数据库, 应该是可以的, 玩家皮肤的数据量够了)

最好的情况是我们找得到一个能用cloudflare worker的人, 这样能用一些基于nodejs的东西, 和discuz!联动也会方便一些
我不认为直接在discuz!上写所有代码是一个好选择, 因为我不太确定它有没有图片处理的一些库, 而且时间成本会很高(对我来说)

悲, 我寻思我已经不是那个可以无视时间成本的人了

附一些我之前写的代码
```javascript
const PNG = require('pngjs').PNG;

async function tick(env) {
await env.MCDB.prepare(
      "DELETE FROM mc WHERE createTime < ?"
      )
      .bind(Date.now() - 2*300000)
      .run();
}

export async function getSession(playerName, env) {
tick(env);

let find = false
let id = 0;
while (!find) {
    id = Math.floor(Math.random()*2147483647);
    const { results } = await env.MCDB.prepare(
      "SELECT * FROM mc WHERE sessionId = ?"
      )
      .bind(id)
      .all();
      find = (results.length == 0);
}

let skin = "";


let res;
let req = new Request("https://api.mojang.com/users/profiles/minecraft/" + playerName);
res = await fetch(req).then(response => response.json()).then(data => {
    return data;
});

req = new Request("https://sessionserver.mojang.com/session/minecraft/profile/" + res.id);
res = await fetch(req).then(response => response.json()).then(data => {
    return data;
});
res = JSON.parse(atob(res.properties.value)).textures.SKIN.url;

let response = await fetch(res);

new PNG({ filterType: 4 }).parse(await response.arrayBuffer(), async function (error, data) {
    for (var i = 0; i < 64; i++) {
      for (var j = 0; j < 64; j++) {
      var idx = (64 * i + j) << 2;
      var x = data.data;
      var y = data.data;
      var z = data.data;
      var a = data.data;

      if (i >= 8 || j >= 8) {
          if (x < 16) {
            skin += "0";
          }
          skin += x.toString(16);
          if (y < 16) {
            skin += "0";
          }
          skin += y.toString(16);
          if (z < 16) {
            skin += "0";
          }
          skin += z.toString(16);
          if (a < 16) {
            skin += "0";
          }
          skin += a.toString(16);
      } else {
          skin += Math.floor(Math.random()*16).toString(16);
          skin += Math.floor(Math.random()*16).toString(16);
          skin += Math.floor(Math.random()*16).toString(16);
          skin += Math.floor(Math.random()*16).toString(16);
          skin += Math.floor(Math.random()*16).toString(16);
          skin += Math.floor(Math.random()*16).toString(16);
          skin += "ff"
      }
    }
}

await env.MCDB.prepare(
      "INSERT INTO mc (sessionId, name, createTime, skin) VALUES (?, ?, ?, ?)"
    )
    .bind(id, playerName, Date.now(), skin)
    .run();
});

return id;
}

export async function getSkin(playerName, id, env) {
tick(env);

try {
    const { results } = await env.MCDB.prepare(
      "SELECT * FROM mc WHERE sessionId = ?"
      )
      .bind(id)
      .all();

    if (results.name != playerName) {
      return -1;
    }
    return results.skin;
} catch(e) {
      return -1;
}

return -1;
}

export async function verify(playerName, id, env) {
tick(env);

const { results } = await env.MCDB.prepare(
      "SELECT * FROM mc WHERE sessionId = ?"
      )
      .bind(id)
      .all();

if (results.name != playerName) {
    return -1;
}
const skinSt = results.skin;

let res;
let req = new Request("https://api.mojang.com/users/profiles/minecraft/" + playerName);
res = await fetch(req).then(response => response.json()).then(data => {
    return data;
});

req = new Request("https://sessionserver.mojang.com/session/minecraft/profile/" + res.id);
res = await fetch(req).then(response => response.json()).then(data => {
    return data;
});
res = JSON.parse(atob(res.properties.value)).textures.SKIN.url;

let response = await fetch(res);

new PNG({ filterType: 4 }).parse(await response.arrayBuffer(), function (error, data) {
    let counterSt = 0;
    let flag = true;

    for (var i = 0; i < 64; i++) {
      for (var j = 0; j < 64; j++) {
      var f = counterSt * 8;
      var a = parseInt(skinSt.substring(f, f + 2), 16);
      var b = parseInt(skinSt.substring(f + 2, f + 4), 16);
      var c = parseInt(skinSt.substring(f + 4, f + 6), 16);
      counterSt++;

      var idx = (64 * i + j) << 2;
      var x = data.data;
      var y = data.data;
      var z = data.data;

      //console.log(a + " " + b + " " + c + " " + x + " " + y + " " + z);

      if (x != a || y != b || z != c) {
          flag = false;
          //console.log(a + " " + b + " " + c + " " + x + " " + y + " " + z + " pi " + i + " pj " + j);
          break;
      }
      }
      if (!flag) {
      break;
      }
    }

    if (flag) {
      env.MCDB.prepare(
      "UPDATE mc SET verify = '1' WHERE sessionId = ?"
      )
      .bind(results.sessionId)
      .run();
    }
});
}

export async function getResult(playerName, id, env) {
tick(env);

try {
    const { results } = await env.MCDB.prepare(
      "SELECT * FROM mc WHERE sessionId = ?"
      )
      .bind(id)
      .all();

    if (results.name != playerName) {
      return false;
    }
    return results.verify;
} catch(e) {
      return false;
}

return false;
}
```

扔在这里, 有谁有能力的或许能实现罢

WisW 发表于 昨天 13:21

确实,这要是老bbs会发生两件事,首先我这个帖子必会有回复
其次我这个回复会被扣分{:...:}
页: [1]
查看完整版本: 新的正版验证可行性分析?