×

服务器内容

分析一下“WebWhiteList”插件

sheepxray sheepxray 发表于2022-04-20 14:03:47 浏览156 评论0

抢沙发发表评论

//今天给大家整点分析
//看起来这个插件既有LLSE的部分,也有JS,以及Node的调用,因此就来简单的分析一下
//版权所有 https://www.minebbs.com/threads/webwhitelist.10179/
//LiteXLoader Dev Helper
/// <reference path="C:/LXLbc/JS/Api.js" /> 


ll.registerPlugin("WebWhitelist", "一个可以用网站申请白名单的白名单插件", {"major":2,"minor":2,"revision":0}, {"发布网站":"https://www.minebbs.com/resources/webwhitelist.3654/","插件作者":"嘿嘿"})
//在LiteLader中注册插件并添加插件描述
//配置文件
var conf=new IniConfigFile(".\\plugins\\WebWhitelist\\conf.ini")
var dt_b=new JsonConfigFile(".\\plugins\\WebWhitelist\\Web\\data.json")
var dt_a=new JsonConfigFile(".\\plugins\\WebWhitelist\\data.json")
//定义conf.ini为ini格式的配置文件
conf.init("白名单申请网站","端口",3000)
conf.init("API接口","是否开启",false)
conf.init("API接口","API密钥",system.randomGuid())
conf.init("API接口","API接口端口",3001)
conf.init("语言","没有白名单的提示","您未获邀在此服务器上游玩!")
conf.init("语言","被拉黑提示","您被拉黑了!")
//初始化conf.ini的内容,层层向下。
//配置Node配置文件
var nc={}
//定义新变量数组nc
    nc["list_port"]=conf.getInt("白名单申请网站","端口")
    //从conf.类中读取-白名单申请网站-端口-X的X值
if(conf.getBool("API接口","是否开启")){
//读取-API接口-是否开启的布尔值
    nc["api"]=true
    nc["api_key"]=conf.getStr("API接口","API密钥")
    nc["api_port"]=conf.getInt("API接口","API接口端口")
    //对应端口密钥读取
    File.writeTo(".\\plugins\\WebWhitelist\\Web\\datax",dt_a.read())
    setInterval(()=>{
        File.writeTo(".\\plugins\\WebWhitelist\\Web\\datax",dt_a.read())
    },1000)
}
else{
    nc["api"]=false
}
File.writeTo(".\\plugins\\WebWhitelist\\Web\\node_conf.json",Wdata.toJson(nc))
//启动Node
system.newProcess(".\\plugins\\WebWhitelist\\Web\\start.bat",()=>{})
//注册监听
mc.listen("onJoin",(pl)=>{
    dt_b.reload()
    //进服刷新数据至\web\data.json
    if(dt_b.get(pl.name)==null && dt_a.get(pl.xuid)==null){
        pl.kick(conf.getStr("语言","没有白名单的提示"))
        //使用if语句xuid所对应的玩家名进行校验,如果没有,即踢出,并输出conf.ini中字符串内 语言-没有白名单的提示-X
    }
    else{
        if(dt_a.get(pl.xuid)==null){
            let ls={}
                ls["name"]=pl.name
                ls["ban"]=false
            dt_a.init(pl.xuid,ls)
            pl.tell(`[提示]您的白名单已转正!`)
            dt_b.delete(pl.name)
            //将玩家的xuid载入.\data.json
        }
        if(dt_a.get(pl.xuid).ban==true){
            pl.kick(conf.getStr("语言","被拉黑提示"))
        }
    }
})  
//注册命令
mc.listen("onServerStarted",()=>{
    let cmd=mc.newCommand("wwl","Web白名单")
    cmd.setEnum("p",["in","ban","unban"])
    cmd.setEnum("h",["help"])
    cmd.mandatory("pl",ParamType.Enum,"p","pl",1)
    cmd.mandatory("help",ParamType.Enum,"h","help",1)
    cmd.mandatory("xn",ParamType.Message,"","xn",1)
    cmd.overload(["pl","xn"])
    cmd.overload(["help"])
    cmd.setCallback((cmd,ori,out,res)=>{
        //确认权限
        if(ori.player!=null){if(ori.player.isOP()==false){return}}
        if(res.pl=="in"){
            //查询xuid记录
            if(dt_a.get(res.xn)!=null){
                out.success(`[玩家信息] XBOXID:${dt_a.get(res.xn).name} 是否被ban:${dt_a.get(res.xn).ban}`)
            }
            else{
                //在玩家数据库里寻找
                if(dt_a.get(data.name2xuid(res.xn))!=null){
                    out.success(`[玩家信息] XBOXID:${dt_a.get(data.name2xuid(res.xn)).name} 是否被ban:${dt_a.get(data.name2xuid(res.xn)).ban}`)
                }
                else{
                    out.error(`§c[ERROR]§r未找到玩家信息!`)
                }
            }
        }
        if(res.pl=="ban"){
            //查询xuid记录
            if(dt_a.get(res.xn)!=null){
                let ls=dt_a.get(res.xn)
                if(ls.ban){
                    out.error(`§c[ERROR]§r玩家已经被拉黑了!`)
                }else{
                    ls["ban"]=true
                    dt_a.set(res.xn,ls)
                    out.success(`[提示]玩家拉黑成功!`)
                }
            }
            else{
                //在玩家数据库里寻找
                if(dt_a.get(data.name2xuid(res.xn))!=null){
                    let ls=dt_a.get(data.name2xuid(res.xn))
                    if(ls.ban){
                        out.error(`§c[ERROR]§r玩家已经被拉黑了!`)
                    }else{
                        ls["ban"]=true
                        dt_a.set(res.xn,ls)
                        out.success(`[提示]玩家拉黑成功!`)
                    }
                }
                else{
                    out.error(`§c[ERROR]§r未找到玩家信息!`)
                }
            }
        }
        if(res.pl=="unban"){
            //查询xuid记录
            if(dt_a.get(res.xn)!=null){
                let ls=dt_a.get(res.xn)
                if(ls.ban==false){
                    out.error(`§c[ERROR]§r玩家并没有被拉黑!`)
                }else{
                    ls["ban"]=false
                    dt_a.set(res.xn,ls)
                    out.success(`[提示]解拉黑成功!`)
                }
            }
            else{
                //在玩家数据库里寻找
                if(dt_a.get(data.name2xuid(res.xn))!=null){
                    let ls=dt_a.get(data.name2xuid(res.xn))
                    if(ls.ban==false){
                        out.error(`§c[ERROR]§r玩家并没有被拉黑!`)
                    }else{
                        ls["ban"]=false
                        dt_a.set(res.xn,ls)
                        out.success(`[提示]解拉黑成功!`)
                    }
                }
                else{
                    out.error(`§c[ERROR]§r未找到玩家信息!`)
                }
            }
        }
        if(res.help!=null){
            out.addMessage(`[wwl命令介绍]`)
            out.addMessage(`[查询玩家信息]/wwl in <玩家id或xuid>`)
            out.addMessage(`[拉黑玩家]/wwl ban <玩家id或xuid>`)
            out.addMessage(`[解除拉黑]/wwl unban <玩家id或xuid>`)
            out.addMessage(`[帮助]/wwl help`)
            out.addMessage(`[拉黑介绍]被拉黑玩家不能再次申请白名单,也不能进入服务器!`)
        }
    })
    cmd.setup()
})
//打印信息
log("WebWhitelist加载成功!")
log("输入 ll plugins WebWhitelist 查看具体信息吧!")

上面是被LLSE加载的部分,下面是启动node的批处理文件

cd ./plugins/WebWhitelist/Web
start node.exe app.js

由此,我们可以看到app.js作为主脚本被node启动接下来我们分析一下app.js

console.log(">>>>>>>>>>开始加载<<<<<<<<<<")
var http = require('http');
var qu = require('querystring');
var fs = require("fs");
var url = require('url');
console.log("模块初始化成功!")
var html_y=fs.readFileSync('index.html');
var postHTML = html_y.toString()
console.log("HTML模板初始化成功!")
var conf_y= fs.readFileSync('node_conf.json');
var conf=JSON.parse(conf_y)
http.createServer(function (req, res) {
  var conf_y= fs.readFileSync('node_conf.json');
  var conf=JSON.parse(conf_y)
  var html_y=fs.readFileSync('index.html');
  var postHTML = html_y.toString()
  var body = "";
  req.on('data', function (chunk) {
    body += chunk;
  });
  req.on('end', function () {
    //判断请求路径是否合法
    if(req.url=="/app.js"||req.url=="/data.json"||req.url=="/node.exe"||req.url=="/node_conf.json"||req.url=="/Receipt.html"||req.url=="/start.bat"){
      res.writeHead(403, {'Content-Type': 'text/html; charset=utf8'});
      res.end(fs.readFileSync('403.html').toString());return
    }
    //返回数据
    res.writeHead(200, {'Content-Type': 'text/html; charset=utf8'});
    console.log(`${req.connection.remoteAddress}请求${req.url}`)
    if(req.url!="/"){
        if(fs.existsSync(`.${req.url}`)){
          res.writeHead(200, {'Content-Type': 'text/html; charset=utf8'});
          res.end(fs.readFileSync(`.${req.url}`).toString());return}
        else{
          res.writeHead(404, {'Content-Type': 'text/html; charset=utf8'});
          res.end(fs.readFileSync('404.html').toString());return
        }
    }
    body = qu.parse(body);
    if(body.xboxid && body.qq) {
        let dt = fs.readFileSync('data.json');
        let data=JSON.parse(dt.toString())
        let a=body.xboxid
        data[a]=body.qq
        let dt_s=JSON.stringify(data,null,"\t")
        fs.writeFile('data.json',dt_s,(err)=>{
            if(err!=null){
                console.error(err)
            }
        })
        res.write(fs.readFileSync('Receipt.html').toString());
    } else {
        res.write(postHTML);
    }
    res.end();
  });
}).listen(conf.list_port);
console.log("监听注册成功!")
console.log(">>>>>>>>>>加载完毕<<<<<<<<<<")
console.log(`白名单登记网站访问地址:

if(conf.api){
  http.createServer(function (req, res) {
    var conf_y= fs.readFileSync('node_conf.json');
    var conf=JSON.parse(conf_y)
    let par = url.parse(req.url, true).query;
    if(par.key==conf.api_key){
        let xx_y=fs.readFileSync('datax');
        let xx=JSON.parse(xx_y)
        if(xx[par.xuid]==null){
            res.writeHead(200, {'Content-Type': 'text/html; charset=utf8'});
            res.end(`{"state":404,"message":"未找到此玩家!/申请白名单后未进服。"}`);
            console.error("API请求未找到玩家!")
        }
        else{
          let pl=xx[par.xuid]
          res.writeHead(200, {'Content-Type': 'text/html; charset=utf8'});
          res.end(`{"state":200,"data":{"name":"${pl["name"]}","qq":"${pl["qq"]}","ban":${pl["ban"]}},"message":"查询成功!"}`);
          console.log("API请求成功!")
        }
     }
     else{
      res.writeHead(200, {'Content-Type': 'text/html; charset=utf8'});
      res.write('{"state":405,"message":"密钥错误!"}')
      console.error("API申请密钥错误!")
      res.end()
     }
  }).listen(conf.api_port);
  console.log(`API访问地址:http://127.0.0.1:${conf.api_port}/`)
}
else{
  console.log("API未开启!")
}

让我们结合主网站的html一起看

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>SADC-WhiteList</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
        html {
            height: 100%;
        }
        body {
            height: 100%;
        }
        .container {
            height: 100%;
            background-image: linear-gradient(to right, #fbc2eb, #a6c1ee);
        }
        .login-wrapper {
            background-color: #fff;
            width: 358px;
            height: 588px;
            border-radius: 15px;
            padding: 0 50px;
            position: relative;
            left: 50%;
            top: 50%;
            transform: translate(-50%, -50%);
        }
        .header {
            font-size: 38px;
            font-weight: bold;
            text-align: center;
            line-height: 200px;
        }
        .input-item {
            display: block;
            width: 100%;
            margin-bottom: 20px;
            border: 0;
            padding: 10px;
            border-bottom: 1px solid rgb(128, 125, 125);
            font-size: 15px;
            outline: none;
        }
        .input-item:placeholder {
            text-transform: uppercase;
        }
        .btn {
            text-align: center;
            padding: 10px;
            width: 100%;
            margin-top: 40px;
            background-image: linear-gradient(to right, #a6c1ee, #fbc2eb);
            color: #fff;
        }
        .msg {
            text-align: center;
            line-height: 88px;
        }
        a {
            text-decoration-line: none;
            color: #abc1ee;
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="login-wrapper">
            <div class="header">填写信息</div>
            <div class="form-wrapper">
                <form method="post">
                    您的游戏ID:<input name="xboxid"><br>
                    您的QQ号:<input name="qq"><br>
                    <input type="submit">
               </form>
            </div>
            <div class="msg">
                SADC服务器白名单申请系统
            </div>
        </div>
    </div>
</body>
</html>

然而我还是没有搞懂WebWhiteList/data.json的写入原理(

shwx52

访客