智能合约开发-如何实现一键化登录Dapp

任何有帐户体系的网站和 app 都会有自己的登录模块,有时候还会集成 oauth2 (weibo, weixin,github)一键化登录.开发者肯定也都或多或少的开发过注册,登录的功能。那么基于以太坊的 Dapp 中登录功能会有什么区别呢?本文主要介绍了 Dapp 帐号体系的构成,以及如何基于 Metamask 开发一键化登录的功能。

首先 Dapp 跟普通的网站(app)没多少区别,完全可以延续之前的帐号体系登录,注册。在需要用到以太坊区块链的时候(比如创建交易,支付等)调用钱包或者 MetaMask 插件即可。

当然本身以太坊就有自己的帐号,每个人都可以创建 Address 来和区块链交互,所以如果我们的 Dapp 跟 Address 能够绑定并实现登录的话,整体的体验会好很多。

解决方案是利用私钥对 payload 加密生成 signature,然后再用

ecdsa_recover 方法对 signature 解密可以拿到对应的公钥。

我们来看下具体的步骤 (默认已经安装 MetaMask)

(1)前端点击登录按钮,首先通过 `web3.eth.accounts[0]` 拿到 publicAddress,然后去后端拿 nonce

httpClient.post('/api/user', {address})
复制代码

(2)后端拿到 address 后,会去数据库查询是否存在这个用户,如果有,则直接返回跟 address 对应的 nonce。没有的话,会执行一个注册用户的过程,同样返回 nonce。

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    public_address = models.CharField(max_length=256)
    nonce = models.IntegerField()

def user()
    public_address = boby.get("address")
    profiles = Profile.objects.filter(public_address=public_address.lower())
    
    if not profiles.exists():
        user = User.objects.create(username=public_address.lower())
        profile = Profile.objects.create(user=user, public_address=public_address.lower(), nonce=generate_nonce())
    else:
        profile = profiles[0]
    return profile
复制代码

(3) 前端拿到 nonce 之后会去找 MetaMask 签名生成 signature

web3.personal.sign(nonce, public_address, callback);
复制代码

(4) 最后拿 signature 和 address 到后端验证是否签名正确

httpClient.post('/api/login', {address, signature});
复制代码

(5) 后端验证,验证成功则完成登录(基于 session 或 jwt)操作。

message_hash = defunct_hash_message(text="signature nonce:%s" % profile.nonce)
recover_address = w3.eth.account.recoverHash(message_hash, signature=signature)
if recover_address and recover_address.lower() == public_address:
    user_login(request, profile.user)
复制代码

这里面的 recoverHash 函数是 python web3.py 模块的。由于以太坊的椭圆曲线加密函数签名参数与比特币不太一样,所以如果用其他椭圆加解密包没法验证通过的话,可查看是不是参数设置不同。

(6) 登录成功后,前后端交互就跟普通 http 请求没什么区别了。

借用一张图来说明登录流程 (challenge 跟上文的 nonce 一致)

最后,我们其实可以看到目前这个登录方式强依赖于 MetaMask 插件,对于手机端 App 是无效的,需要有专门的钱包 app 来完成签名等功能。不过可以展望下,如果 Dapp 越来越多,那么这些基础插件会越来越丰富和完善。

参考链接:

1. One-click Login with Blockchain: A MetaMask Tutorial

2. amaurymartiny/login-with-metamask-demo

3. m0t0k1ch1/metamask-login-sample