Post on: 2025-9-14Last edited: 2025-9-14Words 2320Read Time 6 min

type
status
date
slug
summary
tags
category
icon
password
项目基本上已经完成了。但是还存在一些实际上会出现的问题。(你可以想想有哪些问题)
但是在这些问题中,我们要解决一个比较大的问题:如何证明是我发起的调用
 
在当前我们的项目中,只用 address 作为身份传参,进行一系列信息获取和写入。address 是一个非常公开的东西,任意一个人都可以使用你的 address 作为传参,向服务器发送请求,获取你账号上的信息,比如你是什么时候创建的项目、参与的项目,付费多少(假设),历史付费情况(假设)等等不包含在合约中的其他有价值的私密信息,更甚至直接修改你账号的信息。(就好比别人拿你的手机号直接就读取了你各个网站的信息,甚至还乱改信息)
 
在web3的钱包账户中,无需向某个服务端注册,账户由链上生成,包含一对公钥私钥,由公钥派生出地址。我们能向外界暴露的,只有一个 address。你可以粗暴的认为,address 是账号,是暴露的,私钥privatekey 是密码,是只有你知道的。
 
在我们目前互联网广泛使用的账户体系中,通常是使用账号密码,或者手机验证码的形式进行登录,登录后会在客户端中存放一个认证Token,后续需要鉴权获取用户身份的请求,都带上这个Token存放在请求体的Header中,发送给服务端,服务端进行校验与放行。也就是说,服务器端的数据库里面是存放着各个注册的账号的信息的,因此可以进行登录以及后续鉴权。
 
我们的私钥是绝对绝对不能暴露和对外界提供的,谁掌握了私钥谁就彻底掌握这个钱包。因此我们不能使用目前世界上广泛使用的账户密码的模型。
 
那么如何证明这个地址是我的地址,这个调用是由我本人当前登录的这个账号发起的呢?
 
答案:签名
简单来说,用私钥对一条消息(message)进行签名(signature),使用签名(signature)对消息(message)进行运算解密,能解密恢复出来address ,比较签名者的 address 与解密出来的 address 就能知道是否由本人调用。
该过程使用钱包提供的签名功能即可。
因此我们可以提供两种方案:
  1. 一次签名:
    1. 在登录页面发起第一次需要鉴权的交互时进行签名。服务端验证签名是否正确,如果正确,为这 address 生成一个token,随后逻辑与web2中广泛的流程类似。
  1. 每次签名。
    1. 每次需要鉴权交互时进行签名。
方案1 是实际应用中应该采用的方案,由读者有兴趣自行实现。
我们下面使用方案2,主要是为了展示签名与验证鉴权的过程。

功能实现

我们只用 Create Project 功能作为演示,因为其他功能点都是一样的实现,就不重复了。

钱包签名

我们先使用一下签名。我们在前端调用的时候,发起一个签名调用,先看看签名是怎么一回事。
我们创建 src/lib/signature.ts ,创建签名的 hook 。使用 wagmi 提供的 useSignMessage 来实现。
src/lib/signature.ts
src/app/project/components/CreateProjectFormDialog.tsx
我们在创建项目的处理函数中,导入刚才编写的自定义签名 hook,并且使用弹窗展示签名后的消息。
然后在你创建项目的时候,会弹出一个确认签名的按钮,点击确认,就可以看到浏览器的 alert 弹窗,显示的就是这条消息的签名信息。恢复出来的地址也是我们签名的账户地址(anvil-0)。
因此,我们对前端签名的过程就已经了解了,我们要做的就是前端签名,传递给后端 address,signature,message,后端根据signature,message 恢复出address,并与传入的address做比较即可完成验证。

验证签名

现在,我们在服务端编写验证的函数。
我们新建一个文件,位于 cryptoo/signature.go
详细介绍就看代码注释吧!
我们可以简单验证一下这个函数的正确性,你也可以打印一下从公钥恢复的地址,与传入的 address进行比对。

接口参数改造

在上述过程通过后,我们就可以着手改造我们的代码了。
首先在前端,还是用 create project 这个接口作为示例,因此我们需要改变一下原来的接口传参。

前端

后端

api/request.go 文件中,我们为CreateProjectApi 的绑定结构体也对应地新增两个字段。
api/project.api.go文件中,我们在绑定参数后,执行签名验证。

小结

这一小节介绍了如何使用 wagmi + geth 进行签名和校验,从而确认某个请求确实是由掌握钱包的本人发起调用。

Loading...
从0到1实现一个Dapp全栈项目FairTicket✨(5)项目演示

从0到1实现一个Dapp全栈项目FairTicket✨(5)项目演示


从0到1实现一个Dapp全栈项目FairTicket✨(7)总结展望

从0到1实现一个Dapp全栈项目FairTicket✨(7)总结展望