以太坊和Metamask开发web应用时不再需要密码
我在ConsenSys為各種客戶構(gòu)建了大量的概念證明,通常他們想要利用以太坊區(qū)塊鏈來解決某些業(yè)務(wù)用例。奇怪的是,這些系統(tǒng)通常設(shè)計(jì)有標(biāo)準(zhǔn)的網(wǎng)絡(luò)登錄(即用戶名和密碼)。我總是問自己為什么我還在這樣做設(shè)計(jì),畢竟,這是今天以太網(wǎng)目前可以解決每個(gè)煩人的Web應(yīng)用程序的一個(gè)方面。所以我決定停下腳步,設(shè)計(jì)一下這個(gè)解決方案。
JSON Web token
登錄標(biāo)準(zhǔn)Web系統(tǒng)(和/或使用其API)的一種非常流行的方法是將密碼(經(jīng)過哈希的客戶端)提交給認(rèn)證端點(diǎn)并接收token作為回報(bào)。這通常稱為JSON Web Token,通常在一段有限的時(shí)間內(nèi)(幾分鐘到幾天)有效。這是一個(gè)關(guān)于標(biāo)準(zhǔn)實(shí)現(xiàn)的很好的教程。
JSON Web Token很好,我開始認(rèn)為在區(qū)塊鏈上驗(yàn)證自己很容易。事實(shí)上,當(dāng)你使用以太坊時(shí),你需要不斷地去改進(jìn)。
如果你將以太網(wǎng)地址(這只是公鑰的sha3哈希)視為網(wǎng)站上的帳戶,則可以通過使用私鑰對一段數(shù)據(jù)進(jìn)行簽名來證明你擁有該帳戶,這非常容易。此數(shù)據(jù)是任意的,可以是網(wǎng)站API提供的任意隨機(jī)字符串。因此,我們可以使用地址作為用戶名并繞過密碼的需要。事實(shí)上,我們甚至不需要使用區(qū)塊鏈來做到這一點(diǎn)。
這是使用Express的樣子:
首先,我們需要使用私鑰進(jìn)行橢圓曲線簽名:
var ethUtil = require(‘ethereumjs-util’); // >=5.1.1 var data = ‘i am a string’; // Elliptic curve signature must be done on the Keccak256 Sha3 hash of a piece of data. var message = ethUtil.toBuffer(data); var msgHash = ethUtil.hashPersonalMessage(message); var sig = ethUtil.ecsign(msgHash, privateKey); var serialized = ethUtil.bufferToHex(this.concatSig(sig.v, sig.r, sig.s)) return serialized不要過分擔(dān)心這些參數(shù)是什么。這里有一些密碼學(xué),我鼓勵(lì)你閱讀橢圓曲線簽名。比特幣維基是一個(gè)不錯(cuò)的起點(diǎn)。
無論如何,一旦我們有了簽名組件,我們就可以將它們與用戶的地址一起打包并將其全部發(fā)送到認(rèn)證端點(diǎn)。
POST/Authenticate
var jwt = require(‘jsonwebtoken’); var ethUtil = require('ethereumjs-util'); function checkSig(req, res) {var sig = req.sig;var owner = req.owner;// Same data as beforevar data = ‘i am a string’;var message = ethUtil.toBuffer(data)var msgHash = ethUtil.hashPersonalMessage(message)// Get the address of whoever signed this message var signature = ethUtil.toBuffer(sig)var sigParams = ethUtil.fromRpcSig(signature)var publicKey = ethUtil.ecrecover(msgHash, sigParams.v, sigParams.r, sigParams.s)var sender = ethUtil.publicToAddress(publicKey)var addr = ethUtil.bufferToHex(sender)// Determine if it is the same address as 'owner' var match = false;if (addr == owner) { match = true; }if (match) {// If the signature matches the owner supplied, create a// JSON web token for the owner that expires in 24 hours.var token = jwt.sign({user: req.body.addr}, ‘i am another string’, { expiresIn: “1d” });res.send(200, { success: 1, token: token })} else {// If the signature doesn’t match, error outres.send(500, { err: ‘Signature did not match.’});} }所以基本上,給定一些數(shù)據(jù),一個(gè)地址和一個(gè)EC簽名的組件,我們可以安全的證明該地址屬于簽署數(shù)據(jù)的人。很酷,對吧?
一旦我們對簽名和地址匹配感到滿意,我們就可以為該地址服務(wù)器端簽署一個(gè)JSON Web token。 在這種情況下,token有效期為1天。
現(xiàn)在我們只需要放入一些中間件來保護(hù)任何服務(wù)或修改受保護(hù)信息的路由。
middleware/auth.js
function auth(req, res, next) {jwt.verify(req.body.token, ‘i am another string’, function(err, decoded) {if (err) { res.send(500, { error: ‘Failed to authenticate token.’}); }else {req.user = decoded.user;next();};}); }app.js
// Routes app.post(‘/UpdateData’, auth, Routes.UpdateData); …如果提供的Token對應(yīng)于發(fā)送請求的用戶,我們將繼續(xù)請求路由。請注意,中間件會(huì)修改請求。我們需要引用這個(gè)新的user參數(shù),因?yàn)槲覀冎浪呀?jīng)在我們的中間件中設(shè)置了。
POST/UpdateData
function UpdateData(req, res) {// Only use the user that was set in req by auth middleware!var user = req.user;updateYourData(user, req.body.data);... }我們終于搞定它了! 你的用戶已經(jīng)完全登錄,但不需要密碼。
UI方面
用戶如何在瀏覽器中實(shí)際簽署此數(shù)據(jù)?Metamask會(huì)提供幫助!Metamask是一個(gè)整潔的chrome擴(kuò)展,它將web3注入你的瀏覽器窗口。
mycomponent.jsx
makeSig(dispatch) {function toHex(s) {var hex = ‘’;for(var i=0;i<s.length;i++) { hex += ‘’+s.charCodeAt(i).toString(16); }return `0x${hex}`;}var data = toHex(‘i am a string’);web3.currentProvider.sendAsync({ id: 1, method: 'personal_sign', params: [web3.eth.accounts[0], data] },function(err, result) {let sig = result.result;dispatch(exchange.authenticate(sig, user))})} } render(){let { dispatch, _main: { sig } } = this.props;if (Object.keys(sig).length == 0) { this.makeSig(dispatch); }return (<p>I am a webpage</p>); }這將觸發(fā)Metamask彈出一個(gè)窗口,要求用戶對消息進(jìn)行簽名:
一旦調(diào)用了回調(diào),它將調(diào)用以下操作:
authenticate(sig, user) {return (dispatch) => {fetch(`${this.api}/Authenticate`, {method: 'POST',body: JSON.stringify({ owner: user, sig: sig}),headers: { "Content-Type": "application/json" }}).then((res) => { return res.text(); }).then((body) => {var token = JSON.parse(body).token;dispatch({ type: 'SET_AUTH_TOKEN', result: token})})} }一旦你在reducer中保存了auth token,你就可以調(diào)用經(jīng)過身份驗(yàn)證的端點(diǎn)。我們終于得到它了!
請注意,必須從簽名中恢復(fù)v,r和s值。Metamask有一個(gè)簽名util模塊,用于顯示簽名的構(gòu)造方式。它可以像這樣解構(gòu):
var solidity_sha3 = require('solidity-sha3').default; let hash = solidity_sha3(data); let sig = result.result.substr(2, result.result.length); let r = sig.substr(0, 64); let s = sig.substr(64, 64); let v = parseInt(sig.substr(128, 2));其中r將被解析為0或1.另請注意,這使用solidity-sha3模塊來確保此哈希算法與用作solidity本機(jī)hash方法的哈希算法相同(我們正在hash之前簽名的十六進(jìn)制字符串))。
生產(chǎn)準(zhǔn)備
我無法強(qiáng)調(diào)使用JSON Web token的每個(gè)Web應(yīng)用程序今天都可以輕松利用這一點(diǎn)。具有Metamask擴(kuò)展的任何用戶都可以簡單地繞過登錄屏幕,其安全性可能比目前用于管理登錄的任何內(nèi)容都要好。這意味著更少的忘記密碼,更少的浪費(fèi)時(shí)間和更快樂的用戶群。
而且,你知道,如果你希望你的用戶在沒有中間人的情況下向?qū)Ψ?#xff08;或你或使用此用戶的任何其他系統(tǒng)上的用戶)付款,或者如果你想要利用以太坊的其他百萬其他功能,那么你需要也這樣做。
今天開始,加入我們以太坊,去征服世界。
======================================================================
分享一些以太坊、EOS、比特幣等區(qū)塊鏈相關(guān)的交互式在線編程實(shí)戰(zhàn)教程:
- java以太坊開發(fā)教程,主要是針對java和android程序員進(jìn)行區(qū)塊鏈以太坊開發(fā)的web3j詳解。
- python以太坊,主要是針對python工程師使用web3.py進(jìn)行區(qū)塊鏈以太坊開發(fā)的詳解。
- php以太坊,主要是介紹使用php進(jìn)行智能合約開發(fā)交互,進(jìn)行賬號創(chuàng)建、交易、轉(zhuǎn)賬、代幣開發(fā)以及過濾器和交易等內(nèi)容。
- 以太坊入門教程,主要介紹智能合約與dapp應(yīng)用開發(fā),適合入門。
- 以太坊開發(fā)進(jìn)階教程,主要是介紹使用node.js、mongodb、區(qū)塊鏈、ipfs實(shí)現(xiàn)去中心化電商DApp實(shí)戰(zhàn),適合進(jìn)階。
- C#以太坊,主要講解如何使用C#開發(fā)基于.Net的以太坊應(yīng)用,包括賬戶管理、狀態(tài)與交易、智能合約開發(fā)與交互、過濾器和交易等。
- EOS教程,本課程幫助你快速入門EOS區(qū)塊鏈去中心化應(yīng)用的開發(fā),內(nèi)容涵蓋EOS工具鏈、賬戶與錢包、發(fā)行代幣、智能合約開發(fā)與部署、使用代碼與智能合約交互等核心知識(shí)點(diǎn),最后綜合運(yùn)用各知識(shí)點(diǎn)完成一個(gè)便簽DApp的開發(fā)。
- java比特幣開發(fā)教程,本課程面向初學(xué)者,內(nèi)容即涵蓋比特幣的核心概念,例如區(qū)塊鏈存儲(chǔ)、去中心化共識(shí)機(jī)制、密鑰與腳本、交易與UTXO等,同時(shí)也詳細(xì)講解如何在Java代碼中集成比特幣支持功能,例如創(chuàng)建地址、管理錢包、構(gòu)造裸交易等,是Java工程師不可多得的比特幣開發(fā)學(xué)習(xí)課程。
- php比特幣開發(fā)教程,本課程面向初學(xué)者,內(nèi)容即涵蓋比特幣的核心概念,例如區(qū)塊鏈存儲(chǔ)、去中心化共識(shí)機(jī)制、密鑰與腳本、交易與UTXO等,同時(shí)也詳細(xì)講解如何在Php代碼中集成比特幣支持功能,例如創(chuàng)建地址、管理錢包、構(gòu)造裸交易等,是Php工程師不可多得的比特幣開發(fā)學(xué)習(xí)課程。
- tendermint區(qū)塊鏈開發(fā)詳解,本課程適合希望使用tendermint進(jìn)行區(qū)塊鏈開發(fā)的工程師,課程內(nèi)容即包括tendermint應(yīng)用開發(fā)模型中的核心概念,例如ABCI接口、默克爾樹、多版本狀態(tài)庫等,也包括代幣發(fā)行等豐富的實(shí)操代碼,是go語言工程師快速入門區(qū)塊鏈開發(fā)的最佳選擇。
匯智網(wǎng)原創(chuàng)翻譯,轉(zhuǎn)載請標(biāo)明出處。這里是原文不要再在以太坊和Metamask開發(fā)web時(shí)使用密碼
《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀總結(jié)
以上是生活随笔為你收集整理的以太坊和Metamask开发web应用时不再需要密码的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 深度学习参数怎么调优,这12个trick
- 下一篇: 9号团队-团队任务4:每日立会(2018