{"content":{"title":"DID登陆-MetaMask","body":"# 实现原理\r\n\r\n![3328cbd382804497973d6de31c59b446.png](https:\/\/img.learnblockchain.cn\/attachments\/2022\/09\/0UWePhrh631574b2e7fee.png!\/scale\/50)\r\n\r\n\r\n# 参考文献\r\n[One-click Login with Blockchain: A MetaMask Tutorial](https:\/\/www.toptal.com\/ethereum\/one-click-login-flows-a-metamask-tutorial#how-the-login-flow-works)\r\n\r\n# 以太坊接口文档\r\n[JSON RPC · ethereum\/wiki Wiki](https:\/\/github.com\/ethereum\/wiki\/wiki\/JSON-RPC)\r\n\r\n# 优势\r\n - **提高安全性**：通过公钥加密证明所有权可以说比通过电子邮件\/密码或第三方证明所有权更安全，因为 MetaMask将凭据存储在本地计算机上，而不是在线服务器上，这使得攻击面更小。\r\n -  **简化的用户体验**：快速登陆，无需输入或记住任何密码。\r\n - **增加隐私**：无需电子邮件，不涉及第三方。\r\n\r\n# 缺陷\r\n - **用户需要安装 MetaMask**：如果没有 MetaMaskAPP或安装插件的浏览器，这个登录流程显然是行不通的。如果受众用户对Web3不感兴趣或者未知，他们甚至会考虑安装 MetaMask的可能性很小。\r\n - **后端集成工作**：要将其集成到现有的复杂系统中，需要对涉及身份验证的所有业务进行一些更改：注册、数据库、身份验证路由等。因为每个帐户都将与一个或多个公共地址相关联。\r\n - **WEB及APP端工作**：要通过唤醒MetaMask软件进行消息签名并传递给后端\r\n\r\n# 后端代码实现\r\n 1. 底层实现\r\n```java\r\npublic static void main(String[] args) {\r\n    Credentials credentials = Credentials.create(privatekey);\r\n    String message = \"Hello\";\r\n    byte[] hashMsg = Hash.sha3(message.getBytes());\r\n    Sign.SignatureData signature = Sign.signMessage(hashMsg, credentials.getEcKeyPair(), false);\r\n    byte[] sig_data = ByteBuffer.allocate(signature.getR().length + signature.getS().length + signature.getV().length)\r\n            .put(signature.getR())\r\n            .put(signature.getS())\r\n            .put(signature.getV())\r\n            .array();\r\n    final String hexSig = Numeric.toHexStringNoPrefix(sig_data);\r\n    System.out.printf(\"签名后的字符串：%s\\n\", hexSig);\r\n}\r\n```\r\n 2. 接口实现\r\n```java\r\n@PostMapping(\"\/oauthLogin\/metamask\")\r\npublic ResultVo metaMaskLogin(@Valid @RequestBody MetamaskLoginReq metamaskLoginReq) {\r\n    String publicAddress = metamaskLoginReq.getPublicAddress();\r\n    String signature = metamaskLoginReq.getSignature();\r\n    String message = metamaskLoginReq.getMessage();\r\n\r\n    \/\/ 地址合法性校验\r\n    if (!WalletUtils.isValidAddress(publicAddress)) {\r\n        return ResultVo.fail(\"地址格式非法！\");\r\n    }\r\n\r\n    \/\/ 校验签名信息\r\n    if (!CryptoUtils.validate(signature, message, publicAddress)) {\r\n        return ResultVo.fail(\"签名校验失败！\");\r\n    }\r\n    \r\n    \/\/认证通过之后 开始业务处理\r\n    return ResultVo.success();\r\n}\r\n```\r\n\r\n# 成功效果：\r\n\r\n![在这里插入图片描述](https:\/\/img-blog.csdnimg.cn\/e2ba0312d34f4b11b724b12501cb4e5e.png)\r\n\r\n# 失败效果：\r\n![在这里插入图片描述](https:\/\/img-blog.csdnimg.cn\/0456c62968684fbbaabdb48dc8279cfb.png)\r\n![在这里插入图片描述](https:\/\/img-blog.csdnimg.cn\/02abbb876bf54e8eb394615f7b9dfabc.png)"},"author":{"user":"https:\/\/learnblockchain.cn\/people\/3580","address":null},"history":"QmTGECnYBSGdHrBFQKDE69Qcs13QUaJ1agfmeszyjUnxnG","timestamp":1662350535,"version":1}