第二十九課 如何實(shí)現(xiàn)MetaMask簽名授權(quán)后DAPP一鍵登錄功能?

1庞萍, 摘要

網(wǎng)站太多拧烦,各種用戶名/密碼實(shí)在記不住。所以我們逐漸接受了BAT賬號的授權(quán)登錄功能钝计。在以太坊DAPP應(yīng)用中恋博,也可以使用MetaMask實(shí)現(xiàn)授權(quán)后一鍵登錄功能。MetaMask是去中心化錢包私恬,授權(quán)信息不會如BAT中心一樣存在被收集利用的問題债沮。
本文從技術(shù)層面講清楚原理,并結(jié)合代碼說明如何實(shí)現(xiàn)本鸣。

2疫衩,授權(quán)一鍵式登錄的利弊分析

我們往往被自己的密碼難住,越來越抵制傳統(tǒng)的電子郵件/密碼注冊流程荣德。通過微信闷煤,QQ,支付寶涮瞻,F(xiàn)acebook鲤拿,Google或GitHub一鍵式社交登錄功能可以省去記住密碼或者密碼泄露的而風(fēng)險(xiǎn)。當(dāng)然饲宛,它也需要權(quán)衡利弊皆愉。

社交媒體登錄集成的優(yōu)點(diǎn):

  • 沒有更麻煩的填表。
  • 無需記住另一個(gè)用戶名/密碼對艇抠。
  • 整個(gè)過程需要幾秒鐘而不是幾分鐘幕庐。

社交媒體登錄集成的缺點(diǎn):

  • 由于用戶的信息是從外部提供商處加載的,因此這會對提供商如何使用所有這些個(gè)人數(shù)據(jù)產(chǎn)生巨大的隱私擔(dān)憂家淤。例如异剥,在撰寫本文時(shí),F(xiàn)acebook正面臨著數(shù)據(jù)隱私問題絮重。

加密貓(https://www.cryptokitties.co/)游戲中冤寿,用戶不需要輸入用戶名,密碼就可以建立自己的賬戶體系青伤,進(jìn)行登錄交易督怜。

1.簽名導(dǎo)入-cancel.png

本文介紹下這個(gè)方法的原理和代碼實(shí)現(xiàn),使用MetaMask擴(kuò)展的一鍵式加密安全登錄流程狠角,所有數(shù)據(jù)都存儲在我們自己的后端号杠。我們稱為“使用MetaMask登錄”。

一張價(jià)值千言萬語的圖片,這里是我們要構(gòu)建的登錄流程的演示:

顯示MetaMask登錄演示的動畫姨蟋。

看起來不錯(cuò)屉凯?讓我們開始吧!

3眼溶, 如何使用Metamask進(jìn)行一鍵式登錄流程

一鍵式登錄流程的基本思想是悠砚,通過使用私鑰對一段數(shù)據(jù)進(jìn)行簽名,可以很容易地通過加密方式證明帳戶的所有權(quán)堂飞。如果您設(shè)法簽署由我們的后端生成的精確數(shù)據(jù)灌旧,那么后端將認(rèn)為您是該錢包地址的所有者。因此绰筛,我們可以構(gòu)建基于消息簽名的身份驗(yàn)證機(jī)制节榜,并將用戶的錢包地址作為其標(biāo)識符。

如果它看起來不太清楚别智,那就沒問題了,因?yàn)槲覀儠鹨唤忉屗?/p>

請注意稼稿,雖然我們將使用連接到以太坊區(qū)塊鏈的工具(MetaMask薄榛,以太坊錢包地址),但此登錄過程實(shí)際上并不需要區(qū)塊鏈:它只需要其加密功能让歼。話雖如此敞恋,隨著MetaMask成為如此受歡迎的擴(kuò)展,現(xiàn)在似乎是介紹此登錄流程的好時(shí)機(jī)谋右。

4硬猫, MetaMask瀏覽器擴(kuò)展

如果您已經(jīng)知道MetaMask是什么,請?zhí)^本節(jié)改执。

MetaMask是一個(gè)瀏覽器插件啸蜜,可作為MetaMask Chrome擴(kuò)展Firefox附加組件使用。它的核心是它作為以太坊錢包:通過安裝它辈挂,您將可以訪問一個(gè)獨(dú)特的以太坊錢包地址衬横,您可以使用它開始發(fā)送和接收以太幣或ERC20通證。

但MetaMask不僅僅是以太坊錢包终蒂。作為瀏覽器擴(kuò)展蜂林,它可以與您正在瀏覽的當(dāng)前網(wǎng)頁進(jìn)行交互。它通過在您訪問的每個(gè)網(wǎng)頁中注入一個(gè)名為web3.js的JavaScript庫來實(shí)現(xiàn)拇泣。注入后噪叙,web3將通過window.web3的JavaScript代碼為你訪問的每個(gè)網(wǎng)頁提供一個(gè)對象。要查看此對象霉翔,只需在Chrome或Firefox DevTools控制臺鍵入window.web3(如果已安裝MetaMask)睁蕾,結(jié)果如下圖。

web3.js

Web3.js是以太坊區(qū)塊鏈的JavaScript接口早龟。有以下功能:

  • 獲取最新的區(qū)塊號(web3.eth.getBlockNumber
  • 檢查MetaMask上的當(dāng)前活動帳戶(web3.eth.coinbase
  • 獲取任何帳戶的余額(web3.eth.getBalance
  • 發(fā)送交易(web3.eth.sendTransaction
  • 使用當(dāng)前帳戶的私鑰對消息進(jìn)行簽名(web3.personal.sign
  • ......還有點(diǎn)擊獲取更多接口說明

安裝MetaMask時(shí)惫霸,任何前端代碼都可以訪問所有這些功能猫缭,并與區(qū)塊鏈進(jìn)行交互。他們被稱為dappsDApps(去中心化的應(yīng)用程序壹店,有時(shí)甚至寫成“?Apps”)猜丹。

與DApp開發(fā)相關(guān): 時(shí)間鎖定錢包:以太坊智能合約簡介

web3.js中的大多數(shù)函數(shù)都是讀函數(shù)(get block, get balance, etc.),web3立即給出響應(yīng)硅卢。但是射窒,某些功能(如web3.eth.sendTransactionweb3.personal.sign)需要當(dāng)前帳戶使用其私鑰對某些數(shù)據(jù)進(jìn)行簽名。這些函數(shù)觸發(fā)MetaMask顯示確認(rèn)彈窗将塑,以仔細(xì)檢查用戶是否知道他或她正在簽名的內(nèi)容脉顿。

讓我們看看如何使用MetaMask。要進(jìn)行簡單測試点寥,請?jiān)贒evTools控制臺中粘貼以下行:

web3.personal.sign(web3.fromUtf8("你好艾疟,我是輝哥!!"), web3.eth.coinbase, console.log);

此命令表示:使用coinbase帳戶(即當(dāng)前帳戶)將我的消息(從utf8轉(zhuǎn)換為十六進(jìn)制)進(jìn)行簽名敢辩,并以打印作為回調(diào)函數(shù)打印出簽名蔽莱。輸入回車后,將出現(xiàn)MetaMask彈窗戚长,如果點(diǎn)擊簽名按鈕盗冷,將打印簽名的消息。

MetaMask確認(rèn)彈出窗口

我們將web3.personal.sign在登錄流程中使用同廉。

關(guān)于這一部分的最后一點(diǎn)說明:MetaMask將web3.js注入到您當(dāng)前的瀏覽器中仪糖,但實(shí)際上還有其他獨(dú)立的瀏覽器也會注入web3.js,例如Mist迫肖。但是锅劝,在我看來,MetaMask為普通用戶提供了探索dapps的最佳用戶體驗(yàn)和最簡單的轉(zhuǎn)換蟆湖。

4鸠天, 登錄流程如何工作

這是如何做到的呢?這部分內(nèi)容講說服你帐姻,證明這種方式是安全的稠集。所以為什么部分的介紹就比較短了。

如前面所述饥瓷,我們將忘記區(qū)塊鏈剥纷。我們有一個(gè)傳統(tǒng)的Web 2.0客戶端 - 服務(wù)器RESTful架構(gòu)。我們將做出一個(gè)假設(shè):訪問我們的前端網(wǎng)頁的所有用戶都安裝了MetaMask呢铆。有了這個(gè)假設(shè)晦鞋,我們將展示無密碼加密安全登錄流程的工作原理。

第1步:修改用戶模型(后端)

首先,我們的User模型需要有兩個(gè)新的必填字段:publicAddressnonce悠垛。此外线定,publicAddress需要具有唯一性。你可以保持平常username确买,emailpassword字段斤讥,特別是如果你想平行實(shí)現(xiàn)您MetaMask登錄電子郵件/密碼登錄,但它們是可選的湾趾。

如果用戶希望使用MetaMask登錄芭商,則注冊過程也會略有不同,因?yàn)樽詴r(shí)publicAddress將是必填字段搀缠。不過請放心铛楣,用戶永遠(yuǎn)不需要手動輸入publicAddress錢包地址,因?yàn)樗梢酝ㄟ^web3.eth.coinbase變量來提取艺普。

第2步:生成隨機(jī)數(shù)(后端)

對于數(shù)據(jù)庫中的每個(gè)用戶簸州,在nonce字段中生成隨機(jī)字符串。例如歧譬,nonce可以是一個(gè)大的隨機(jī)整數(shù)勿侯。

第3步:用戶獲取他們的隨機(jī)數(shù)(前端)

在我們的前端JavaScript代碼中,假設(shè)存在MetaMask缴罗,我們可以訪問window.web3。因此祭埂,我們可以通知web3.eth.coinbase獲取當(dāng)前MetaMask帳戶的錢包地址面氓。

當(dāng)用戶單擊登錄按鈕時(shí),我們向后端發(fā)出API調(diào)用以檢索與其錢包地址關(guān)聯(lián)的隨機(jī)數(shù)蛆橡。像帶參數(shù)獲取例如GET /api/users?publicAddress=${publicAddress}應(yīng)該做的事情那樣舌界。當(dāng)然,由于這是一個(gè)未經(jīng)身份驗(yàn)證的API調(diào)用泰演,因此后端應(yīng)配置為僅顯示此路由上的公共信息包括nonce呻拌。

如果先前的請求未返回任何結(jié)果,則表示當(dāng)前錢包地址尚未注冊睦焕。我們需要先通過POST /users傳遞publicAddress請求消息體來創(chuàng)建一個(gè)新帳戶藐握。另一方面,如果有結(jié)果垃喊,那么我們存儲它的nonce猾普。

第4步:用戶簽署Nonce(前端)

一旦前端接收nonce到先前API調(diào)用的響應(yīng),它將運(yùn)行以下代碼:

web3.personal.sign(nonce, web3.eth.coinbase, callback);

這將提示MetaMask顯示用于簽名消息的確認(rèn)彈出窗口本谜。隨機(jī)數(shù)將顯示在此彈出窗口中初家,以便用戶知道她或他有沒有簽署某些惡意數(shù)據(jù)。

當(dāng)她或他接受簽名時(shí),將使用帶簽名的消息(稱為signature)作為參數(shù)調(diào)用回調(diào)函數(shù)溜在。然后前端進(jìn)行另一個(gè)API調(diào)用POST /api/authentication陌知,傳遞一個(gè)帶有signaturepublicAddress的消息體。

第5步:簽名驗(yàn)證(后端)

當(dāng)后端收到POST /api/authentication請求時(shí)掖肋,它首先根據(jù)請求消息體中publicAddress獲取數(shù)據(jù)庫中的對應(yīng)用戶仆葡,特別是它相關(guān)的隨機(jī)數(shù)nonce

具有隨機(jī)數(shù)培遵,錢包地址和簽名后浙芙,后端可以加密地驗(yàn)證用戶已正確簽署了隨機(jī)數(shù)。如果確認(rèn)是這種情況籽腕,那么用戶已經(jīng)證明了擁有錢包地址的所有權(quán)嗡呼,我們可以考慮對她或他進(jìn)行身份驗(yàn)證。然后可以將JWT或會話標(biāo)識符返回到前端皇耗。

第6步:更改Nonce(后端)

為了防止用戶使用相同的簽名再次登錄(如果它被泄露)南窗,我們確保下次同一用戶想要登錄時(shí),她或他需要簽署一個(gè)新的nonce郎楼。這是通過nonce為該用戶生成另一個(gè)隨機(jī)數(shù)并將其持久保存到數(shù)據(jù)庫來實(shí)現(xiàn)的万伤。

這就是我們管理nonce簽名無密碼登錄流程的方法。

5呜袁,為什么登錄流程有效

根據(jù)定義敌买,身份驗(yàn)證實(shí)際上只是帳戶所有權(quán)的證明。如果您使用錢包地址唯一地標(biāo)識您的帳戶阶界,那么證明您加密方式擁有該帳戶就非常簡單虹钮。

為了防止黑客獲取某個(gè)特定郵件及其簽名(但不是您的實(shí)際私鑰),我們會強(qiáng)制需要簽名的消息滿足以下條件:

    1. 由后端提供
    1. 定期改變

在我們的demo樣例中膘融,每次成功登錄后我們都改變了它芙粱,但也可以設(shè)想基于時(shí)間戳的機(jī)制。

MetaMask登錄流程的六個(gè)步驟概述氧映。

6春畔, DEMO代碼實(shí)現(xiàn)

在本節(jié)中,我將逐一完成上述六個(gè)步驟岛都。我將展示一些代碼片段律姨,以便我們?nèi)绾螐念^開始構(gòu)建此登錄流,或者將其集成到現(xiàn)有的后端臼疫,而不需要太多努力线召。

為了本文的目的,我創(chuàng)建了一個(gè)小型演示應(yīng)用程序多矮。我正在使用的堆棧如下:

  • Node.js缓淹,Express和SQLite(通過Sequelize ORM)在后端實(shí)現(xiàn)RESTful API哈打。它在成功驗(yàn)證時(shí)返回JWT。
  • 在前端反應(yīng)單頁面應(yīng)用程序讯壶。

我嘗試使用盡可能少的庫料仗。我希望代碼足夠簡單,以便您可以輕松地將其移植到其他技術(shù)堆棧伏蚊。

訪問https://login-with-metamask.firebaseapp.com/可以獲得一個(gè)演示立轧,也可以參考步驟搭建自己的本地工程。

歡迎加入輝哥的知識星球躏吊,從中下載本案例代碼工程氛改,也可加專門微信群交流技術(shù)問題。

image.png

第1步:修改用戶模型(后端)

需要兩個(gè)字段:publicAddressnonce比伏。我們初始化nonce為隨機(jī)大數(shù)胜卤。每次成功登錄后都應(yīng)更改此號碼。我還在username這里添加了一個(gè)可選字段赁项,用戶可以更改葛躏。

.\backend\src\models\user.model.js

const User = sequelize.define('User', {
  nonce: {
    allowNull: false,
    type: Sequelize.INTEGER.UNSIGNED,
    defaultValue: () => Math.floor(Math.random() * 1000000) // Initialize with a random nonce
  },
  publicAddress: {
    allowNull: false,
    type: Sequelize.STRING,
    unique: true,
    validate: { isLowercase: true }
  },
  username: {
    type: Sequelize.STRING,
    unique: true
  }
});

為簡單起見,我將publicAddress字段設(shè)置為小寫悠菜。更嚴(yán)格的檢查地址是否是有效的以太坊地址的方法參考鏈接:https://ethereum.stackexchange.com/questions/1374/how-can-i-check-if-an-ethereum-address-is-valid)舰攒。

第2步:生成隨機(jī)數(shù)(后端)

這是在defaultValue()上面的模型定義中的函數(shù)中完成的。

第3步:用戶獲取他們的隨機(jī)數(shù)(前端)

下一步是在后端添加一些樣板代碼來處理User模型上的CRUD方法悔醋,我們在這里不做摩窃。

切換到前端代碼,當(dāng)用戶單擊登錄按鈕時(shí)芬骄,我們的handleClick處理程序執(zhí)行以下操作:

.\frontend\src\Login\Login.js

class Login extends Component {
  handleClick = () => {
    // --snip--
    const publicAddress = web3.eth.coinbase.toLowerCase();

    // Check if user with current publicAddress is already present on back end
    fetch(`${process.env.REACT_APP_BACKEND_URL}/users?publicAddress=${publicAddress}`)
      .then(response => response.json())
      // If yes, retrieve it. If no, create it.
      .then(
        users => (users.length ? users[0] : this.handleSignup(publicAddress))
      )
      // --snip--
  };

  handleSignup = publicAddress =>
    fetch(`${process.env.REACT_APP_BACKEND_URL}/users`, {
      body: JSON.stringify({ publicAddress }),
      headers: {
        'Content-Type': 'application/json'
      },
      method: 'POST'
    }).then(response => response.json());
}

在這里猾愿,我們正在檢索MetaMask活動帳戶web3.eth.coinbase。然后我們檢查publicAddress后端是否已經(jīng)存在德玫。如果用戶已經(jīng)存在,我們就獲取用戶信息椎麦。要么就是在handleSignup方法中創(chuàng)建一個(gè)新帳戶宰僧。

第4步:用戶簽署Nonce(前端)

讓我們繼續(xù)我們的handleClick方法。我們現(xiàn)在擁有一個(gè)由后端給出的用戶(無論是檢索還是新創(chuàng)建)观挎。特別是我們有他們的noncepublicAddress琴儿。因此,我們準(zhǔn)備publicAddress使用與此相關(guān)聯(lián)的私鑰對nonce進(jìn)行簽名web3.personal.sign嘁捷。這是在handleSignMessage函數(shù)中完成的造成。

請注意,web3.personal.sign將字符串的十六進(jìn)制表示作為其第一個(gè)參數(shù)雄嚣。我們需要使用UTF-8編碼的字符串轉(zhuǎn)換為十六進(jìn)制格式web3.fromUtf8晒屎。此外喘蟆,我決定簽署一個(gè)更加用戶友好的句子,而不是僅簽署nonce鼓鲁,因?yàn)樗鼘@示在MetaMask確認(rèn)彈出窗口中:I am signing my once-time nonce: ${nonce}蕴轨。

class Login extends Component {
  handleClick = () => {
    // --snip--
    fetch(`${process.env.REACT_APP_BACKEND_URL}/users?publicAddress=${publicAddress}`)
      .then(response => response.json())
      // If yes, retrieve it. If no, create it.
      .then(
        users => (users.length ? users[0] : this.handleSignup(publicAddress))
      )
      // Popup MetaMask confirmation modal to sign message
      .then(this.handleSignMessage)
      // Send signature to back end on the /auth route
      .then(this.handleAuthenticate)
      // --snip--
  };

  handleSignMessage = ({ publicAddress, nonce }) => {
    return new Promise((resolve, reject) =>
      web3.personal.sign(
        web3.fromUtf8(`I am signing my one-time nonce: ${nonce}`),
        publicAddress,
        (err, signature) => {
          if (err) return reject(err);
          return resolve({ publicAddress, signature });
        }
      )
    );
  };

  handleAuthenticate = ({ publicAddress, signature }) =>
    fetch(`${process.env.REACT_APP_BACKEND_URL}/auth`, {
      body: JSON.stringify({ publicAddress, signature }),
      headers: {
        'Content-Type': 'application/json'
      },
      method: 'POST'
    }).then(response => response.json());
}

當(dāng)用戶成功簽署消息后,我們將轉(zhuǎn)到該handleAuthenticate方法骇吭。我們只是向/auth后端的路由發(fā)送請求橙弱,發(fā)送我們publicAddress以及signature用戶剛簽名的消息。

第5步:簽名驗(yàn)證(后端)

這是稍微復(fù)雜一點(diǎn)的部分燥狰。后端在/auth包含一個(gè) publicAddress和一個(gè)路由上接收請求簽名signature棘脐,并且需要驗(yàn)證錢包地址publicAddress是否已簽名正確的隨機(jī)數(shù)nonce

第一步是從數(shù)據(jù)庫中檢索用戶所說的publicAddress; 只有一個(gè)因?yàn)槲覀?code>publicAddress在數(shù)據(jù)庫中定義為唯一字段龙致。然后蛀缝,我們將消息設(shè)置msg為“I am signing my one-time nonce...”,與步驟4中的前端完全相同净当,使用此用戶的隨機(jī)數(shù)内斯。

下一個(gè)塊是驗(yàn)證本身。有一些加密涉及像啼。如果您喜歡研究俘闯,我建議您閱讀有關(guān)橢圓曲線簽名算法以獲得更多信息。

總結(jié)這部分的作用忽冻,對于給出的msg(包含nonce)和signature信息真朗,ecrecover函數(shù)輸出用于簽名msg的錢包地址。如果它與我們請求消息體的publicAddress一致僧诚,則證明了他們擁有publicAddress的所有權(quán)遮婶。經(jīng)過這個(gè)過程,我們認(rèn)為他們經(jīng)過身份驗(yàn)證的湖笨。

User.findOne({ where: { publicAddress } })
  // --snip--
  .then(user => {
    const msg = `I am signing my one-time nonce: ${user.nonce}`;

    // We now are in possession of msg, publicAddress and signature. We
    // can perform an elliptic curve signature verification with ecrecover
    const msgBuffer = ethUtil.toBuffer(msg);
    const msgHash = ethUtil.hashPersonalMessage(msgBuffer);
    const signatureBuffer = ethUtil.toBuffer(signature);
    const signatureParams = ethUtil.fromRpcSig(signatureBuffer);
    const publicKey = ethUtil.ecrecover(
      msgHash,
      signatureParams.v,
      signatureParams.r,
      signatureParams.s
    );
    const addressBuffer = ethUtil.publicToAddress(publicKey);
    const address = ethUtil.bufferToHex(addressBuffer);

    // The signature verification is successful if the address found with
    // ecrecover matches the initial publicAddress
    if (address.toLowerCase() === publicAddress.toLowerCase()) {
      return user;
    } else {
      return res
        .status(401)
        .send({ error: 'Signature verification failed' });
    }
  })

成功驗(yàn)證后旗扑,后端生成JWT并將其發(fā)送回客戶端。這是一種經(jīng)典的身份驗(yàn)證方案慈省,所以我不會在這里放置代碼臀防。

第6步:更改Nonce(后端)

出于安全原因,最后一步是更改nonce边败。在成功驗(yàn)證后的某處袱衷,添加以下代碼:

// --snip--
.then(user => {
  user.nonce = Math.floor(Math.random() * 1000000);
  return user.save();
})
// --snip--

7,今天就可以投入生產(chǎn)了

雖然區(qū)塊鏈可能有其缺陷并且仍處于早期階段笑窜,但我無法強(qiáng)調(diào)如何在今天的任何現(xiàn)有網(wǎng)站上實(shí)施此登錄流程的重要性致燥。以下是為什么此登錄流程優(yōu)先于電子郵件/密碼社交登錄的參數(shù)列表:

  • 提高安全性:公鑰加密的所有權(quán)證明可以說比通過電子郵件/密碼或第三方證明所有權(quán)更安全,因?yàn)镸etaMask在您的計(jì)算機(jī)本地存儲憑據(jù)排截,而不是在線服務(wù)器嫌蚤,這使得攻擊面較小辐益。
  • 簡化的用戶體驗(yàn):這是一鍵式(也可能是雙擊)登錄流程,在幾秒鐘內(nèi)完成搬葬,無需輸入或記住任何密碼荷腊。
  • 增加隱私:不需要電子郵件,也不涉及第三方急凰。

當(dāng)然女仰,MetaMask登錄流程可以很好地與其他傳統(tǒng)登錄方法并行使用。需要在每個(gè)帳戶與其擁有的錢包地址之間進(jìn)行映射抡锈。

但是這個(gè)登錄流程并不適合所有人:

  • 用戶需要安裝MetaMask:如果沒有MetaMask或支持web3的瀏覽器疾忍,此登錄流程顯然無效。如果您的受眾對加密貨幣不感興趣床三,他們甚至?xí)紤]安裝MetaMask一罩。隨著最近的通證熱潮,讓我們希望我們正在走向Web 3.0互聯(lián)網(wǎng)撇簿。
  • 需要在后端完成一些工作:正如我們所見聂渊,實(shí)現(xiàn)此登錄流程的簡單版本非常簡單。但是四瘫,要將其集成到現(xiàn)有的復(fù)雜系統(tǒng)中汉嗽,需要在接觸身份驗(yàn)證的所有區(qū)域進(jìn)行一些更改:注冊,數(shù)據(jù)庫找蜜,身份驗(yàn)證路由等饼暑。這尤其正確,因?yàn)槊總€(gè)帳戶都將與一個(gè)或多個(gè)錢包地址相關(guān)聯(lián)洗做。
  • 它不適用于移動設(shè)備:看以下描述弓叛。

8, 移動設(shè)備的缺點(diǎn)

正如我們所見诚纸,這web3是此登錄流程的先決條件撰筷。在桌面瀏覽器上,MetaMask會注入它畦徘。但是毕籽,移動瀏覽器沒有擴(kuò)展程序,因此此登錄流程無法在移動版Safari旧烧,Chrome或Firefox上開箱即用影钉。有一些獨(dú)立的移動瀏覽器注入了web3基于MetaMask的瀏覽器画髓。在撰寫本文時(shí)掘剪,它們還處于早期階段,但如果您有興趣奈虾,請查看Cipher夺谁,StatusToshi廉赔。“使用MetaMask登錄”適用于這些移動瀏覽器匾鸥。

關(guān)于移動應(yīng)用程序蜡塌,答案是肯定的,登錄流程有效勿负,但需要有很多準(zhǔn)備工作的作為基礎(chǔ)馏艾。作為基本準(zhǔn)備工作,您需要自己重建一個(gè)簡單的以太坊錢包奴愉。這包括錢包地址生成琅摩,種子文字恢復(fù)和安全私鑰存儲,以及web3.personal.sign確認(rèn)彈出窗口锭硼。幸運(yùn)的是房资,有l(wèi)ibrary可以幫助您。人們關(guān)心的關(guān)鍵信息是安全的檀头,因?yàn)閼?yīng)用程序本身擁有私鑰轰异。在桌面瀏覽器上,我們將此任務(wù)委托給MetaMask暑始。

所以我認(rèn)為答案是否定的搭独,這個(gè)登錄流程今天不適用于移動設(shè)備。但它正朝著這個(gè)方向努力蒋荚,今天簡單的解決方案仍然是移動用戶的并行傳統(tǒng)登錄方法戳稽。
【輝哥備注】雖然主流的移動端瀏覽器APP還不支持MetaMask插件,但是包括TrustWallet, AlphaWallet等錢包自帶的DAPP瀏覽器支持支付功能期升,也就不需要MetaMask錢包用于支付了惊奇。手機(jī)端的一鍵登錄問題轉(zhuǎn)換為別的實(shí)現(xiàn)方案的問題。

9播赁, 環(huán)境搭建

1). 修改IP地址

輝哥采用Windows 環(huán)境下搭建Ubuntu Linux環(huán)境的方式颂郎,在Windows環(huán)境訪問目標(biāo)測試程序,所以需要修改前后端調(diào)用的IP地址為本地地址容为。就是http://192.168.0.103為Ubuntu服務(wù)器的IP地址乓序,如果調(diào)用前端也在linux下運(yùn)行則可使用http://127.0.0.1地址。

.\login-with-metamask-demo\frontend.env.development

REACT_APP_BACKEND_URL=http://192.168.0.103:8000/api

.\login-with-metamask-demo\frontend\src\registerServiceWorker.js

window.location.hostname === 'http://192.168.0.103' ||

修改后坎背,然后把完整的login-with-metamask-demo工程上傳至linux工作目錄下替劈。

2). 安裝依賴并運(yùn)行后端服務(wù)器

在新的命令窗口運(yùn)行以下命令,完成安裝和服務(wù)器運(yùn)行:

npm install -g yarn
yarn
yarn dev

安裝運(yùn)行成功的輸出內(nèi)容:

duncanwang@ubuntu:~/work/login-with-metamask-demo/backend$ yarn dev
yarn run v1.10.1
$ nodemon --exec babel-node src/
[nodemon] 1.17.2
[nodemon] to restart at any time, enter `rs`
[nodemon] watching: *.*
[nodemon] starting `babel-node src/`
sequelize deprecated String based operators are now deprecated. Please use Symbol based operators for better security, read more at http://docs.sequelizejs.com/manual/tutorial/querying.html#operators node_modules/sequelize/lib/sequelize.js:242:13
Express app listening on localhost:8000
^C
duncanwang@ubuntu:~/work/login-with-metamask-demo/backend$ ls
Dockerfile  node_modules  package.json  src  yarn.lock
duncanwang@ubuntu:~/work/login-with-metamask-demo/backend$ rm -r -f node_modules
duncanwang@ubuntu:~/work/login-with-metamask-demo/backend$ ls
Dockerfile  package.json  src  yarn.lock
duncanwang@ubuntu:~/work/login-with-metamask-demo/backend$ npm install -g yarn
/home/duncanwang/.nvm/versions/node/v8.11.4/bin/yarn -> /home/duncanwang/.nvm/versions/node/v8.11.4/lib/node_modules/yarn/bin/yarn.js
/home/duncanwang/.nvm/versions/node/v8.11.4/bin/yarnpkg -> /home/duncanwang/.nvm/versions/node/v8.11.4/lib/node_modules/yarn/bin/yarn.js
+ yarn@1.10.1
updated 1 package in 4.201s
duncanwang@ubuntu:~/work/login-with-metamask-demo/backend$ yarn
yarn install v1.10.1
[1/4] Resolving packages...
[2/4] Fetching packages...
info fsevents@1.1.3: The platform "linux" is incompatible with this module.
info "fsevents@1.1.3" is an optional dependency and failed compatibility check. Excluding it from installation.
[3/4] Linking dependencies...
[4/4] Building fresh packages...
Done in 173.70s.
duncanwang@ubuntu:~/work/login-with-metamask-demo/backend$ yarn dev
yarn run v1.10.1
$ nodemon --exec babel-node src/
[nodemon] 1.17.2
[nodemon] to restart at any time, enter `rs`
[nodemon] watching: *.*
[nodemon] starting `babel-node src/`
sequelize deprecated String based operators are now deprecated. Please use Symbol based operators for better security, read more at http://docs.sequelizejs.com/manual/tutorial/querying.html#operators node_modules/sequelize/lib/sequelize.js:242:13
Express app listening on localhost:8000

3). 安裝依賴并運(yùn)行前端服務(wù)器

在前端程序根目錄下

yarn
yarn start
安裝運(yùn)行成功的輸出內(nèi)容:

duncanwang@ubuntu:~/work/login-with-metamask-demo/frontend$ yarn
yarn install v1.10.1
warning package-lock.json found. Your project contains lock files generated by tools other than Yarn. It is advised not to mix package managers in order to avoid resolution inconsistencies caused by unsynchronized lock files. To clear this warning, remove package-lock.json.
[1/4] Resolving packages...
[2/4] Fetching packages...
info There appears to be trouble with your network connection. Retrying...
info There appears to be trouble with your network connection. Retrying...
info fsevents@1.1.3: The platform "linux" is incompatible with this module.
info "fsevents@1.1.3" is an optional dependency and failed compatibility check. Excluding it from installation.
[3/4] Linking dependencies...
[4/4] Building fresh packages...
success Saved lockfile.
Done in 266.85s.
duncanwang@ubuntu:~/work/login-with-metamask-demo/frontend$ yarn start
yarn run v1.10.1
$ react-scripts start

Starting the development server...


Compiled successfully!

You can now view frontend in the browser.

  Local:            http://localhost:3000/
  On Your Network:  http://192.168.0.103:3000/

Note that the development build is not optimized.
To create a production build, use yarn build.

4). 運(yùn)行客戶端程序并測試授權(quán)一鍵登錄

在Windows瀏覽器運(yùn)行客戶端程序得滤,點(diǎn)擊完成SIGN簽名授權(quán):


登錄后陨献,更新用戶的名字。


不需要輸入密碼懂更,完成了duncanwang和錢包地址0xD1F7922e8b78cBEB182250753ade8379d1E09949的關(guān)聯(lián)和一鍵登錄功能眨业。

10急膀,總結(jié)

我們在本文中介紹了一鍵式,加密安全的登錄流程龄捡,沒有涉及第三方卓嫂,稱為“使用MetaMask登錄”。我們解釋了后端生成的隨機(jī)數(shù)的數(shù)字簽名如何證明帳戶的所有權(quán)聘殖,從而提供身份驗(yàn)證晨雳。我們還探討了這種登錄機(jī)制與傳統(tǒng)電子郵件/密碼或社交登錄相比的權(quán)衡,無論是在桌面還是在移動設(shè)備上奸腺。

即使今天這樣的登錄流程的目標(biāo)受眾仍然很小悍募,我真誠地希望你們中的一些人感到鼓舞,在你自己的網(wǎng)絡(luò)應(yīng)用程序中提供與MetaMask一起登錄洋机,與傳統(tǒng)登錄流程并行坠宴。

本文由輝哥翻譯自《One-click Login with Blockchain: A MetaMask Tutorial》,并做適當(dāng)?shù)男薷囊员阒袊脩艨梢愿玫睦斫狻?/em>

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末绷旗,一起剝皮案震驚了整個(gè)濱河市喜鼓,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌衔肢,老刑警劉巖庄岖,帶你破解...
    沈念sama閱讀 218,682評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異角骤,居然都是意外死亡隅忿,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評論 3 395
  • 文/潘曉璐 我一進(jìn)店門邦尊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來背桐,“玉大人,你說我怎么就攤上這事蝉揍×辞停” “怎么了?”我有些...
    開封第一講書人閱讀 165,083評論 0 355
  • 文/不壞的土叔 我叫張陵又沾,是天一觀的道長弊仪。 經(jīng)常有香客問我,道長杖刷,這世上最難降的妖魔是什么励饵? 我笑而不...
    開封第一講書人閱讀 58,763評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮滑燃,結(jié)果婚禮上役听,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好禾嫉,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,785評論 6 392
  • 文/花漫 我一把揭開白布祈秕。 她就那樣靜靜地躺著嗅蔬,像睡著了一般履恩。 火紅的嫁衣襯著肌膚如雪盖喷。 梳的紋絲不亂的頭發(fā)上煤禽,一...
    開封第一講書人閱讀 51,624評論 1 305
  • 那天港准,我揣著相機(jī)與錄音鹃愤,去河邊找鬼暴凑。 笑死凛篙,一個(gè)胖子當(dāng)著我的面吹牛黍匾,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播呛梆,決...
    沈念sama閱讀 40,358評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼锐涯,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了填物?” 一聲冷哼從身側(cè)響起纹腌,我...
    開封第一講書人閱讀 39,261評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎滞磺,沒想到半個(gè)月后升薯,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,722評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡击困,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年涎劈,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片阅茶。...
    茶點(diǎn)故事閱讀 40,030評論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡蛛枚,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出脸哀,到底是詐尸還是另有隱情坤候,我是刑警寧澤,帶...
    沈念sama閱讀 35,737評論 5 346
  • 正文 年R本政府宣布企蹭,位于F島的核電站白筹,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏谅摄。R本人自食惡果不足惜徒河,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,360評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望送漠。 院中可真熱鬧顽照,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至植影,卻和暖如春裳擎,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背思币。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評論 1 270
  • 我被黑心中介騙來泰國打工鹿响, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人谷饿。 一個(gè)月前我還...
    沈念sama閱讀 48,237評論 3 371
  • 正文 我出身青樓惶我,卻偏偏與公主長得像,于是被迫代替她去往敵國和親博投。 傳聞我的和親對象是個(gè)殘疾皇子绸贡,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,976評論 2 355

推薦閱讀更多精彩內(nèi)容