# 关于NFT提前从网站获取签名

By [JamesTsao的个人成长笔记](https://paragraph.com/@pigfly) · 2022-07-18

---

这篇文章我觉得很有含金量，哈哈。

最近打的NFT项目，有一些是需要从前端获取签名的。这个时候，市面上大部分的Mint工具都未必能过得了这一关。

我在网上搜索了很多的资料，目前关于提前获取签名的教程几乎没有。科学家们的分享基本上都止步于合约mint、16进制mint等常规的mint方法，这些在我之前的文章里面也有提到。目前基本上来说超过半数的人都会这些mint方法，统称为非网页端mint方法吧。

当一个NFT项目限制了必须要获取前端服务器签名才能mint的时候，大部分人就只能干瞪眼或者老老实实去前端mint了（当然前端大概率是抢不到的）。

首先说下限制前端服务器签名才能mint的原理。这里以ApeDog为例。在合约的mint方法中，加了一个限制条件。

    require(isAuthorized(sig,digest),"CONTRACT_MINT_NOT_ALLOWED");
    

就是说，每个钱包都需要提供一个签名才能调用mint的方法。这个签名需要从前端网页获取，是由项目方的钱包进行签署的。用户拿着签名去调用合约的mint方法时，合约就会根据签名反推出签名的内容，如果得到的内容（一般就是调用者的地址）是正确的，那么就允许用户进行mint。理论上，签名应该是对调用者的钱包进行签名，这样就不会出现所有人都共用一个签名的伪签名方式。之前有许多项目出现过类似的BUG，后来的人拿到前面人的签名就可以跳过前端直接合约mint。ApeDog这个项目，不光是对调用者的钱包进行了签名，还为每个签名给定了一个有效时间，过了这个有效时间签名就会作废。这个设置挡住了许多提前获取签名的人。

那么前端是如何拿到签名的呢？我们在前端进行mint的时候，一般先连接小狐狸钱包，然后点击mint的按钮，就会跳出小狐狸窗口了，在小狐狸窗口中提交交易即可进行mint。其实在跳出小狐狸窗口的时候，我们看data里面的内容，就已经包含了我们所需要的签名信息了。这是最正规的获取签名的渠道。如果我们想要通过科学家的方式来获取签名的话，首先需要了解前端获取签名的过程。

当我们点击mint按钮的时候，在前端网页就会触发一个event。这个event就会通过一个接口把我们的钱包地址等信息发给后台，后台在收到这些信息后，会调用项目方的钱包对这些信息进行签名，然后返回给前端。这个就是前端获取签名的基本流程。

所以，如果我们不想老老实实的点击mint按钮去获得签名的话，就需要我们自己直接去调用这个接口来和后台进行互动。

调用接口的方式很简单，一般就是两种方法，GET和POST。获取签名的话一般会用POST。调用POST方法的时候，需要输入两个参数，一个是目标url，一个是headers。url就是接口的地址，headers就是我们需要代入的参数。

那么如何获得接口的url地址呢？两种方法，第一个，在前端页面的上通过f12打开开发者模式，在network选项卡中抓包。点击mint按钮后，找到网页对应发送的post请求，在请求中就可以得到我们需要的url了，顺便还能看到我们的headers中包含的参数，一举两得。这种方法的前提是网页要能打得开，一般情况下，比较火爆的项目在发售的时候，前端都会卡的根本没有机会点击mint按钮…

第二种方法的门槛就比较高了，那就是阅读网页的源代码。大部分的NFT项目的源代码都会暴露在网页上，通过开发者模式就可以查看到。通过f12进入开发者模式下，就可以看到网页的js文件。这些js文件可能也是经过了处理，一般可读性都很差…还是以ApeDog项目为例，因为迄今为止我只从它这找到了接口地址。

在apedog.wtf这个目录下只有一个js文件，所以找起来目标就比较明确了。有的项目目录下还有好多文件，找起来就不太好定位了。

![](https://storage.googleapis.com/papyrus_images/a271e5e4ce51f79c8298819f0e68401de7b95f8050ecdca9f341231a70d17431.png)

点击打开js文件，搜索POST，会出来许多匹配结果。一个一个看一下，看到这里，就需要注意下了。后面跟着一个sigurl。推测这个sigurl就是接口地址。接着搜索sigurl。

![](https://storage.googleapis.com/papyrus_images/de31f9d0046afaf04b3d63aee6166c661ef379689a4ef311d06f2a7041ad69af.png)

这下就看到了，后面的这个url应该就是我们要找的接口url了。接着看，下面一行还有一个auth，这个一般需要写在headers里面，类似一个授权的东西。

![](https://storage.googleapis.com/papyrus_images/6146f3435630e8fa123eb0236f618bef56d74425c21f529927a28721991708a0.png)

接着搜索sigurl，看到这个部分。这里有两个参数，一个是sender，应该就是我们的钱包地址了，还有一个Authorization，就是需要我们刚才看到的auth的内容。那么，接下来我们就可以去调用POST方法了。

![](https://storage.googleapis.com/papyrus_images/f7fa87b90a66b865b764b9df4d6efa320df0461ccd21b214747db9c7199d5d9f.png)

这里用python的request库。

    import requests
    
    url = 'https://1-0-0--wen-wl.rekttt.autocode.gg/'
    auth = 'tok_prod_DxcW8FCKenfdpGDbGD8puUfjqmEYCpPTZ5DijpGLd1XHpzaep19jxyds6y6HLMQ1'
    headers = {
      'user-agent': 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Mobile Safari/537.36',
      'Authorization': 'Bearer ' + auth,
      'sender': 'wallet address'
    }
    
    res = requests.post(url,headers)
    print(res.text)
    

填入我们扒出来的url、auth还有我们自己的钱包地址。运行结果如下：

    {"signature":"0xf5d836dbeb2662e5066256456d8a2d05d6de926d28e4e70861cd90dbd755345710d83b290bce4dfd530042d2c32f8fc2d287a535fcf89187b008baf8e386e816","expireTime":1658179246}
    

看看这是啥，这就是我们需要得到的签名了。我们绕过了前端，直接通过接口的方式提前获取到了签名，拿着这个签名就可以去mint啦。这个方法需要我们能够从js文件中找到接口的地址，还需要弄清楚接口需要发送那些参数，比较考验我们的经验还有阅读代码的能力。不同的项目的代码都是不一样的，所以基本上每个项目都得重新修改获取签名的方式。对于普通玩家就非常不友好了。这里也非常佩服市面上的一些工具，能够自动获取签名，让用户赢在起跑线。不得不说，收费有收费的道理啊！

---

*Originally published on [JamesTsao的个人成长笔记](https://paragraph.com/@pigfly/nft-2)*
