【前言】
终於要进到後端的部分啦!一样先来看 Project 分析,这几天的内容会环绕在第一步**「连动 MetaMask 系统」和第二步「并且得到当前登入者的以太坊地址」**,我研究了很久才终於理解到底该怎麽实作,希望大家可以留下来品味一下!
【(使用者看见的)前端与(後方运作的)後端】
这篇文章的内容我参考来自 MetaMask Docs 的 Ethereum Provider API 以及 Amaury Martiny 的 One-click Login with Blockchain: A MetaMask Tutorial,在文章最下面的参考资料区我都会附上连结。真的非常感谢这些区块链的工程师无私分享自己的智慧结晶!
【Ethereum Provider API】
因为 MetaMask 是一个浏览器插件,所以除了可以被当作以太坊钱包使用外,也可以在网页上藉由每个帐户拥有独一无二的公钥来交易或验证,以及将 ****MetaMask ****当作登入介面使用。
【Login Flow】
在一个登入授权中,我们主要确认使用者的 publicAddress
确实为其所有,并且确保 nonce
的可行性。此外使用者不需要自己输入 publicAddress
因为在登入 MetaMask 之後,我们能透过 web3.eth.coinbase
或相关函式来获取这项资讯。
Click here to install MetaMask
,按下後跳出网页转往下载页面。nonce
。
在资讯安全中,Nonce 是一个在加密通信只能使用一次的数字。在认证协定中,它往往是一个随机或伪随机数,以避免重送攻击。Nonce 也用於串流加密法以确保安全。如果需要使用相同的金钥加密一个以上的讯息,就需要 Nonce 来确保不同的讯息与该金钥加密的金钥流不同。 *节录自维基百科《Nonce》- https://zh.wikipedia.org/zh-tw/Nonc*e
publicAddress
来确认其 nonce
。
nonce
。进入 Login Flow 的下一步。nonce
需要跳出 MetaMask 的登入介面。呈现 Sign-In Message 并且在使用者登入时(输入密码时)呈现 Loading 图示。authentication
,其为一个包含 signature
和 publicAddress
的物件。authentication
****後会进行数位加密签证,以确保这个 nonce
是被这个使用者所登入。以此就可以确保 publicAddress
与拥有者的所有权。nonce
。以上登入流的想法来自於以下这张图,出处为 Amaury Martiny 的 One-click Login with Blockchain: A MetaMask Tutorial。
【MetaMask Extension Check】
今天的内容我想着重在 Login Flow 中的第一步**「检测使用者是否已经下载 MetaMask Chrome extension」**
首先会使用到 @metamask/onboarding
这个套件,其功能为在使用者跳出页面下载 MetaMask 的onboarding 结束後,redirect 回到原先页面。
npm install @metamask/onboarding
import MetaMaskOnboarding from '@metamask/onboarding'
GitHub - MetaMask/metamask-onboarding: A library to help onboard new MetaMask users
准备在 Button 里面呈现的文字以及 styled-components 的资讯。
const ONBOARD_TEXT = 'Click here to install MetaMask!';
// 当 USER 未下载 **MetaMask Chrome extension**
const CONNECT_TEXT = 'Welcome Back to Dino Club!';
// 当 USER 已下载 **MetaMask Chrome extension**
const CONNECTED_TEXT = 'Connected';
// 当 USER 已经连接到 Ethereum 帐户
// styled-components
const clrneon = "#36D7B7";
const StyledButton = styled.button`
...
`;
初始化以及 useState
。
export function OnboardingButton() {
const [buttonText, setButtonText] = useState(ONBOARD_TEXT);
// 按钮要呈现的文字
const [isDisabled, setDisabled] = useState(false);
// 跳出下载页面的时候要使按钮无效
const [accounts, setAccounts] = useState([]);
// 之後要用来记录 使用者的 ethereum 帐号
const onboarding = React.useRef();
...
return (
<StyledButton disabled={isDisabled} onClick={onClick}>
{buttonText}
</StyledButton>
);
}
使用 useEffect
设定 new MetaMaskOnboarding()
跳出 MetaMask Chrome extension 的下载页面。
export function OnboardingButton() {
...
useEffect(() => {
if (!onboarding.current) {
onboarding.current = new MetaMaskOnboarding();
}
}, []);
...
return (
...
);
}
使用 useEffect
根据当前是否下载的状况来改变按钮功能以及呈现的文字。
export function OnboardingButton() {
...
useEffect(() => {
if (MetaMaskOnboarding.isMetaMaskInstalled()) {
if (accounts.length > 0) {
// 在登入之前 acoount 都不会纪录任何资料,所以长度会是 0
setButtonText(CONNECTED_TEXT);
setDisabled(true);
onboarding.current.stopOnboarding();
} else {
setButtonText(CONNECT_TEXT);
setDisabled(false);
}
}
}, [accounts]);
...
return (
...
);
}
【小结】
到这里第一步就大功告成啦!这个部份我用了好几十个小时才成功。不过好在 MetaMask 的 Doc 有提供非常多资源可以使用,所以才能如愿做出来。比较不能完全理解的部分在寻找 window
里面有 ethereum
的元素部件。我会再研究一阵子等有结果再来跟大家分享!
const isMetaMaskInstalled = () => {
//Have to check the ethereum binding on the window object to see if it's installed
const { ethereum } = window;
return Boolean(ethereum && ethereum.isMetaMask);
};
【参考资料】
Introduction | MetaMask Docs
Breaking Change: No Longer Injecting Web3
One-click Login with Blockchain: A MetaMask Tutorial
>>: EP 07 - [TDD] 取得 Nonce (2/2)
传递机制听起来非常没有画面感,於是擅自替传递机制取了绰号叫回力镖,如同回力镖有去程,回程以及猎捕到猎...
经过了一个月的尝试,我们大致上已经掌握了能够自己实现非常基础的 Ruby VM 的能力。虽然在铁人赛...
从前几章IT治理到管理,产出各种规章,执行部门必须依据这些规章完成相应资安防护,以达到提升安全及符合...
9.3 三连通元件 3连通跟2连通真的不太一样。 以2连通来说,如果我们今天把整张图,依照关节点切开...
Spring Boot 的注释是用来告知Spring 框架,底下的程序码代表的意思,并且可以设定相关...