首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C#/PHP如何构建不可滥用的API

C#/PHP如何构建不可滥用的API
EN

Stack Overflow用户
提问于 2020-07-11 19:44:06
回答 1查看 47关注 0票数 0

我正在制作统一多人游戏与镜面网络系统。我想存储球员的数据,如库存,当前位置等在数据库(MySQL)。

我有HTTPS安全的服务器、Unity和以下代码:

( a)为请求生成签名(C#)

代码语言:javascript
复制
    private const string SECRET_KEY_ALPHA = "alpha";
    private const string SECRET_KEY_BETA = "beta";

    private List<string> requestData;
    private string signature;

    public SignatureGenerator(List<string> requestData)
    {
        this.requestData = requestData;
    }

    public string GenerateSign()
    {
        this.signature = "";

        string bodyString = "";
        foreach(string dataPart in this.requestData)
        {
            bodyString += (dataPart + ".");
        }

        bodyString = EncryptMD5(bodyString);
        bodyString += SECRET_KEY_ALPHA;
        bodyString = EncryptSHA1(bodyString);

        this.signature = EncryptHmac(bodyString);

        return this.signature;
    }

    private String EncryptHmac(string combined)
    {
        Encoding ascii = Encoding.ASCII;
        HMACSHA256 hmac = new HMACSHA256(ascii.GetBytes(SECRET_KEY_BETA));
        return Convert.ToBase64String(hmac.ComputeHash(ascii.GetBytes(combined)));
    }

    private String EncryptMD5(string data)
    {
        using(MD5 md5 = MD5.Create())
        {
            byte[] dataBytes = Encoding.UTF8.GetBytes(data);
            byte[] md5Bytes = md5.ComputeHash(dataBytes);
            return BitConverter.ToString(md5Bytes).Replace("-", String.Empty);
        }
    }

    private String EncryptSHA1(string data)
    {
        using (SHA1Managed sha1 = new SHA1Managed())
        {
            var hash = sha1.ComputeHash(Encoding.UTF8.GetBytes(data));
            var sb = new StringBuilder(hash.Length * 2);

            foreach (byte b in hash)
            {
                sb.Append(b.ToString("X2"));
            }

            return sb.ToString();
        }
    }

( b)在服务器上验证签名

代码语言:javascript
复制
define('SECRET_KEY_ALPHA', 'alpha');
define('SECRET_KEY_BETA', 'beta');

class SignatureVerifier
{
    private $bodyString;
    private $providedSignature;
    private $result;

    /**
     * SignatureVerifier constructor.
     * @param $bodyString
     * @param $providedSignature
     */
    public function __construct($bodyString, $providedSignature)
    {
        $this->bodyString = $bodyString;
        $this->providedSignature = $providedSignature;
    }

    public static function generateBodyString($dataArray)
    {
        $result = '';
        foreach ($dataArray as $data)
        {
            $result .= ($data . '.');
        }
        return $result;
    }

    public function verify()
    {
        $generatedSign = sha1(md5($this->bodyString), SECRET_KEY_ALPHA);
        $generatedHmac = hash_hmac('sha256', $generatedSign, SECRET_KEY_BETA);

        $this->result = ($generatedHmac == $this->providedSignature);
    }

    public function success()
    {
        return $this->result;
    }
}

,但这对我有什么不好呢?我有身体和签名,所以我还想要什么?

我的问题是,有人可以捕捉到这个请求(帖子和标志),并开始垃圾处理这些请求,以获得一些项目。

我试过的事情:

  • 向签名

添加时间戳

结果:请求将失败,因为我将不得不发送和接收请求的速度超过秒。

  • 添加令牌到请求,即一次性使用(在使用新生成之后)

结果:如果有人决定在市场上出售他们的物品(网站)-令牌将改变,整个系统将变得腐败,因为游戏将使用,而不是工作,令牌。

摘要:我期望什么?

我期望客户端(统一,C#游戏)和服务器(Apache,PHP)的安全API用法,它们不能被滥用(用捕获的请求发送垃圾邮件),并且是安全的,所以我可以使用它来进行游戏中的库存管理、从游戏中登录等等。

我希望我能为你提供所有必要的数据来解决我的问题。如果你需要更多-评论。

谢谢你提前帮忙。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-07-12 14:31:57

我已经找出了什么是有用的。我很遗憾我没有想过这个问题。

过期日期(时间戳)!

包含到您的请求和签名时间戳,这将定义到期日期的请求。然后在PHP脚本中,验证签名和时间戳(在两个服务中使用相同的时区)。如果当前时间戳大于请求中提供的时间戳,则拒绝请求。

定义应该执行多长时间。日期。我建议提出一些测试请求,以了解游戏联系人API有多长时间。然后及时添加少量内容(以防更长的请求),并享受您更安全的API。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62853790

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档