Unity程序使用统计及授权

文章目录[x]
  1. 0.1:一、前言
  2. 0.2:二、流程
  3. 0.3:三、主要代码
  4. 0.4:四、总结

一、前言

使用Nodejs为unity程序做使用次数统计和授权登录。
这套系统分为三部分:1.Unity模块;2.Nodejs服务;3.管理页面。

二、流程

unity程序登录
  1. unity启动时向服务器请求是否可以登录。
  2. nodejs服务器查询是否存在该id,如果不存在则创建。
  3. nodejs服务器查询要登录的程序名称,如果不存在则返回登录失败。
  4. nodejs服务器查询当前程序是否可以登录,如果不能登录返回登录失败。
  5. nodejs服务器查询当前用户ID是否授权登录,如果没有授权返回登录失败。
  6. nodejs服务器向数据库插入当前用户的登录信息,返回运行登录。
管理页面
  1. 管理员登录。
  2. 查询用户登录记录,带搜索。
  3. 查询用户列表,并且可以修改单个用户的登录权限。
  4. 查询程序列表,并且可以修改单个程序的登录权限。

管理页面是用vue2开发的,主要使用的模块:vue-router,vuex,element-ui。

 

三、主要代码

  1. Unity LoginStats.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using UnityEngine.Networking;

public class LoginStats : MonoBehaviour
{
    public string ProgramName = "测试程序";
    private string uuid = "uid";
    private void Awake()
    {
        QueryClientInfo();
    }
    private void QueryClientInfo()
    {
        string storeId = PlayerPrefs.GetString(uuid, "");
        if (string.IsNullOrEmpty(storeId))
        {
            storeId = Guid.NewGuid().ToString();
            PlayerPrefs.SetString(uuid, storeId);
        }
        RequestAuth(storeId);
    }

    private void RequestAuth(string clientID)
    {
        StartCoroutine(APIRequest(clientID));
    }

    private IEnumerator APIRequest(string clientID)
    {
        WWWForm form = new WWWForm();
        form.AddField("clientID", clientID);
        form.AddField("programName", ProgramName);
        UnityWebRequest req = UnityWebRequest.Post("https://5y5007l723.zicp.fun/api/clientLogin", form);
        yield return req.SendWebRequest();
        if (req.isNetworkError)
        {
            Debug.Log(req.error);
        }
        else
        {
            string res = req.downloadHandler.text;
            Debug.Log(res);
            if(!res.Contains("允许登录"))
            {
                Application.Quit();
            }
        }
    }
}
  1. Nodejs登录接口
/**
 * 客户端登陆接口
 * params:clientID programName ip/mac
 */
router.post("/clientLogin", (req, res) => {
    // var clientid = req.query.clientID;
    // var programname = req.query.programName;
    var clientid = req.body.clientID;
    var programname = req.body.programName;
    //如果使用了内网穿透,此处恒为127.0.0.1,如果前端使用了反向代理此处恒为127.0.0.1
    var ip = req.headers['x-real-ip'] || req.headers['x-forwarded-for'] || req.connection.remoteAddres || req.socket.remoteAddress || '';
    
    var info = {
        clientid: clientid,
        programname: programname,
        ip: ip
    }
    let sql = "select * from clientinfo where clientID=?"
    let arr = [info.clientid];
    sqlFn(sql, arr, result => {
        if (result.length > 0) {
            //存在该客户端
            var currentClient = result[0];
            let sql = "select * from programinfo where programName=?"
            let arr = [info.programname];
            sqlFn(sql, arr, result => {
                if (result.length > 0 && result[0].globalEntry == "true") {
                    //允许全局登陆
                    if (currentClient.allowLogin == "true") {
                        //该客户端允许登陆
                        res.send({ status: 200, msg: '允许登陆' })
                        writeLoginInfo(info.clientid, info.programname, info.ip)
                    }
                    else {
                        //该客户端不允许登陆
                        res.send({ status: 500, msg: '客户端不允许登陆' })
                    }
                }
                else {
                    //不允许全局登陆
                    res.send({ status: 500, msg: '未找到该程序或全局不允许登陆' })
                }
            })
        }
        else {
            //不存在该客户端
            let sql = "insert into clientinfo values(null,?,?,'','true')"
            let arr = [info.clientid, info.ip];
            sqlFn(sql, arr, result => {
                if (result.affectedRows > 0) {
                    //添加新客户端成功
                    let sql = "select * from programinfo where programName=?"
                    let arr = [info.programname];
                    sqlFn(sql, arr, result => {
                        if (result.length > 0 && result[0].globalEntry == "true") {
                            //全局允许登陆
                            res.send({ status: 200, msg: '允许登陆' })
                            writeLoginInfo(info.clientid, info.programname, info.ip)
                        }
                        else {
                            //全局不允许登陆
                            res.send({ status: 500, msg: '全局不允许登陆' })
                        }
                    })
                }
                else {
                    //添加新客户端失败
                    res.send({ status: 500, msg: '客户端添加失败' })
                }
            })

        }
    })

})

四、总结

  1. 1.管理页面放在了云服务器并且使用了CDN加速,服务器放在了本地的虚拟机中,然后使用了免费的花生壳内网穿透。(会导致nodejs拿不到真正的客户IP,只能拿到花生壳也就是本机IP)
  2. 2.管理页面请求接口需要写完整服务器接口路径,如果管理页面中要隐藏服务器地址可以使用nginx做反向代理达到隐藏实际服务器IP的目的。

nginx设置反向代理示例:

server {
        listen       80;
        server_name  localhost;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
            root   C:\Users\A\Desktop\WebGLLocation;
            index  index.html index.htm;
        }

        #为vue设置代理 ’/api‘为请求的规则
        # location /api {
        #     proxy_pass https://5y5007l723.zicp.fun;
        # }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }

 

 

点赞

发表回复

昵称和uid可以选填一个,填邮箱必填(留言回复后将会发邮件给你)
tips:输入uid可以快速获得你的昵称和头像