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
就能知道是否由本人调用。该过程使用钱包提供的签名功能即可。
因此我们可以提供两种方案:
- 一次签名:
在登录页面发起第一次需要鉴权的交互时进行签名。服务端验证签名是否正确,如果正确,为这
address
生成一个token,随后逻辑与web2中广泛的流程类似。- 每次签名。
每次需要鉴权交互时进行签名。
方案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
进行签名和校验,从而确认某个请求确实是由掌握钱包的本人发起调用。- Author:Ago
- URL:http://www.sunago.top/article/fairticket-signature
- Copyright:All articles in this blog, except for special statements, adopt BY-NC-SA agreement. Please indicate the source!