摘要:上一篇用以太坊區(qū)塊鏈保證的安全上我們介紹了基本的解決方案,這一篇我們重點來看客戶端。是以太坊的實現(xiàn)。以太坊,主要是針對工程師使用進行區(qū)塊鏈以太坊開發(fā)的詳解。這里是原文以太坊區(qū)塊鏈的安全設(shè)計
上一篇用以太坊區(qū)塊鏈保證Asp.Net Core的API安全(上)我們介紹了基本的解決方案,這一篇我們重點來看客戶端。
正如我們所說,我們的DApp是一個簡單的HTML/ES6客戶端。我們將在Asp.Net Core 2之上構(gòu)建客戶端,以利用IIS Express和Visual Studio IDE。因此,Startup.cs類中的Configure方法將是:
if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseDefaultFiles(); app.UseStaticFiles();
使DApp成為NPM項目并安裝必備條件以使用ES6 Javascript標準。這不是強制性的,可以使用自己的堆棧構(gòu)建DApp。
從項目文件夾運行Powershell并運行以下NPM命令:
npm init npm install webpack npm install babel-core babel-loader --save-dev npm install babel-preset-es2015 --save-dev npm install babel-preset-stage-0 --save-dev npm install babel-polyfill --save npm install babel-runtime --save npm install babel-plugin-transform-runtime --save-dev
要配置webpack/babel,請使用以下配置創(chuàng)建webpack.config.js文件:
var path = require("path"); module.exports = { entry: [ "babel-polyfill", "./src/main" ], output: { publicPath: "/js/", path: path.join(__dirname, "/wwwroot/js/"), filename: "main.build.js" } };
我們已設(shè)定webpack將src/main.js文件構(gòu)建到/www/js/main.build.js。
安裝以太坊擴展包:
npm install web3 npm install ethereumjs-util
Web3是一個javascript封裝包,它簡化了針對以太坊區(qū)塊鏈的JSON RPC調(diào)用。Ethereumjs-util提供了一些以太坊特定的實用程序。讓我們構(gòu)建一個非常簡單的HTML頁面。我們需要一個登錄按鈕和另一個按鈕來從我們的API層加載一些安全數(shù)據(jù):
Ethereum Jwt Client Ethereum Jwt Client
DApp邏輯將駐留在src/main.js文件中,正如我們在webpack.config.js文件中指定的那樣。src/main.js文件將是:
let ethUtil = require("ethereumjs-util"); let Web3 = require("web3"); let coinbase = null; let accessToken = null; let init = () => { if (typeof web3 !== "undefined") { web3 = new Web3(web3.currentProvider); web3.eth.getCoinbase(function (err, account) { if (err === null && ethUtil.isValidAddress(account)) { coinbase = account; eth_account_span.innerHTML = coinbase; } else { eth_account_span.innerHTML = "Please unlock your account and refresh the page"; console.error(err); } }); } else { eth_account_span.innerHTML = "Please install or unlock Metamask browser plugin or navigate this page with Mist or another web3 browser"; } }; let request = obj => { return new Promise((resolve, reject) => { let xhr = new XMLHttpRequest(); xhr.open(obj.method || "GET", obj.url); if (obj.headers) { Object.keys(obj.headers).forEach(key => { xhr.setRequestHeader(key, obj.headers[key]); }); } xhr.onload = () => { if (xhr.status >= 200 && xhr.status < 300) { resolve(xhr.response); } else { reject(xhr.statusText); } }; xhr.onerror = () => reject(xhr.statusText); xhr.send(obj.body); }); }; login_btn.addEventListener("click", (e) => { e.preventDefault(); login_btn.setAttribute("disabled", "disabled"); login_btn.innerHTML = "Please sign the message"; let plain = "Hi, you request a login from client to Eth Jwt Api. Please sign this message. This is not a transaction, is completely free and 100% secure. We"ll use your signature to prove your ownership over your private key server side."; let msg = ethUtil.bufferToHex(new Buffer(plain, "utf8")); let hash = ethUtil.bufferToHex(ethUtil.keccak256("x19Ethereum Signed Message: " + plain.length + plain)); let from = coinbase; let params = [msg, from]; let method = "personal_sign"; web3.currentProvider.sendAsync({ method, params, from, }, function (err, result) { if (err || result.error) { login_btn.removeAttribute("disabled"); login_btn.innerHTML = "Login"; console.error(err); return console.error(result.error); } console.log({ "signature": result.result, "msg": msg, "hash": hash }); login_btn.innerHTML = "Requesting token..."; let loginData = {}; loginData.signer = from; loginData.signature = result.result; loginData.message = msg; loginData.hash = hash; request({ url: "http://localhost:49443/api/token", body: JSON.stringify(loginData), method: "post", headers: { "Authorization": "Bearer " + accessToken, "Content-type": "application/json" } }).then(data => { var json = JSON.parse(data); accessToken = json.token; console.log("access token: " + accessToken); login_btn.removeAttribute("disabled"); login_btn.innerHTML = "Login"; }).catch(error => { console.error(error); login_btn.removeAttribute("disabled"); login_btn.innerHTML = "Login"; }); }); }); load_data_btn.addEventListener("click", (e) => { e.preventDefault(); request({ url: "http://localhost:49443/api/values", headers: { "Authorization": "Bearer " + accessToken } }).then(data => { var json = JSON.parse(data); for (let i = 0; i < json.length; i++) { data_list.innerHTML += "
1.coinbase和accessToken是全局變量,分別存儲用戶以太坊帳戶和JWT token。
2.init函數(shù)從Metamask提供的提供程序初始化web3對象,然后它嘗試檢索用戶的帳戶(coinbase)。這需要解鎖在Metamask中簽名的帳戶。
3.require函數(shù)只是hxr對象的封裝,可以輕松地向API層調(diào)用ajax。
4.load_data_btn單擊處理程序?qū)PI層安全端點進行ajax調(diào)用。這需要有效的accessToken才能工作,否則,API層將響應(yīng)401 HTTP響應(yīng)。
5.login_btn單擊是一個兩步功能。首先,它要求用戶簽署任意消息。簽名后,它會將帳戶,簽名,明文消息和帶前綴的哈希發(fā)送到令牌端點。
請注意,web3.personal.sign將十六進制格式(0x ...)的普通字符串的字節(jié)數(shù)組作為輸入。
正如我們所說的,服務(wù)器端,我們將使用兩種不同的方式從簽名中恢復(fù)公鑰:在一個中我們將使用JSON RPC 接口中的web3.personal.ecrecover(web3.personal.sign對應(yīng));在另一個中,我們將使用底層的ecrecover離線功能。根據(jù)文檔,web3.personal.sign使用底層簽名函數(shù)來簽署hash和前綴消息,因此,為了使用底層ecrecover對應(yīng),我們還需要計算并將此hash發(fā)送到令牌端點。
運行兩個應(yīng)用程序并使用安裝了Metamask插件的瀏覽器導(dǎo)航到客戶端。請記住,為了將src/main.js文件構(gòu)建到js/main.build.js,你需要從Powershell運行webpac命令。如果一切正常,客戶端將檢索coinbase,你將在頁面上看到你的帳戶:
如果你現(xiàn)在單擊“請求數(shù)據(jù)”按鈕,將獲得HTTP響應(yīng)401。如果單擊“登錄”按鈕,Metamask將提示你簽名:
簽名后,處理程序?qū)α钆贫它c進行ajax調(diào)用。在此階段,身份驗證方法不會檢查任何簽名,因此端點將始終發(fā)出JWT令牌。一旦收到JWT令牌,客戶端就能通過ajax調(diào)用安全端點。如果現(xiàn)在單擊“請求數(shù)據(jù)”按鈕,將收到HTTP響應(yīng)200和數(shù)據(jù)負載:
從簽名中檢索以太坊帳戶到目前為止,EthereumJwtApi是一個簡單的JWT Asp.Net核心示例,因為它不提供任何有效的身份驗證方法。
TokenController的關(guān)鍵部分是兩個Authenticate方法及其從簽名中檢索以太坊帳戶的能力。為此,你需要安裝Nethereum.Web3 NuGet包。Nethereum是以太坊的.Net實現(xiàn)。
Authenticate方法只是對web3.personal.ecrecover函數(shù)進行JSON RPC調(diào)用:
private async TaskAuthenticate(LoginVM login) { UserVM user = null; var client = new RpcClient(new Uri(_config["Nethereum:Geth"])); // Require the RPC endpoint of a Geth node as input eg: http://127.0.0.1:8545 var signer = await client.SendRequestAsync (new RpcRequest(1, "personal_ecRecover", login.Message, login.Signature)); if (signer.ToLower().Equals(login.Signer.ToLower())) { // read user from DB or create a new one // for now we fake a new user user = new UserVM { Account = signer, Name = string.Empty, Email = string.Empty }; } return user; }
PRO:
web3.personal.sign是web3.personal.sign的對應(yīng)部分,因此你無需擔心其底層實現(xiàn)。
缺點:
需要你自己的Geth節(jié)點。不支持Parity,Infura不允許JSON RPC調(diào)用web3.personal.*。Authenticate2方法顯示了另一種方法,它使用底層ecrecover功能的離線實現(xiàn):
private async TaskAuthenticate2(LoginVM login) { UserVM user = null; var signer = new Nethereum.Signer.MessageSigner(); var account = signer.EcRecover(login.Hash.HexToByteArray(), login.Signature); if (account.ToLower().Equals(login.Signer.ToLower())) { // read user from DB or create a new one // for now we fake a new user user = new UserVM { Account = account, Name = string.Empty, Email = string.Empty }; } return user; }
PRO:
不需要JSON RPC調(diào)用就能工作。MessageSigner.EcRecover是Nethereum提供的離線功能。
缺點:
你需要處理web3.personal.sign實現(xiàn)才能正確恢復(fù)帳戶。出于這個原因,在客戶端,我們相應(yīng)地計算了前綴消息哈希。
結(jié)論現(xiàn)在你擁有基本的知識和一個項目的骨架,可以使用以太坊保護你的Asp.Net Core 2 API。只需幾點說明:
web3 1.0.0處于測試階段,web3.personal.sign實現(xiàn)可能會隨著時間的推移而變化。請務(wù)必在你可以維護的代碼庫上使用這種身份驗證方法。也許Infura某天決定允許web3.personal.ecrecover :-)
======================================================================
分享一些以太坊、EOS、比特幣等區(qū)塊鏈相關(guān)的交互式在線編程實戰(zhàn)教程:
java以太坊開發(fā)教程,主要是針對java和android程序員進行區(qū)塊鏈以太坊開發(fā)的web3j詳解。
python以太坊,主要是針對python工程師使用web3.py進行區(qū)塊鏈以太坊開發(fā)的詳解。
php以太坊,主要是介紹使用php進行智能合約開發(fā)交互,進行賬號創(chuàng)建、交易、轉(zhuǎn)賬、代幣開發(fā)以及過濾器和交易等內(nèi)容。
以太坊入門教程,主要介紹智能合約與dapp應(yīng)用開發(fā),適合入門。
以太坊開發(fā)進階教程,主要是介紹使用node.js、mongodb、區(qū)塊鏈、ipfs實現(xiàn)去中心化電商DApp實戰(zhàn),適合進階。
C#以太坊,主要講解如何使用C#開發(fā)基于.Net的以太坊應(yīng)用,包括賬戶管理、狀態(tài)與交易、智能合約開發(fā)與交互、過濾器和交易等。
EOS教程,本課程幫助你快速入門EOS區(qū)塊鏈去中心化應(yīng)用的開發(fā),內(nèi)容涵蓋EOS工具鏈、賬戶與錢包、發(fā)行代幣、智能合約開發(fā)與部署、使用代碼與智能合約交互等核心知識點,最后綜合運用各知識點完成一個便簽DApp的開發(fā)。
java比特幣開發(fā)教程,本課程面向初學(xué)者,內(nèi)容即涵蓋比特幣的核心概念,例如區(qū)塊鏈存儲、去中心化共識機制、密鑰與腳本、交易與UTXO等,同時也詳細講解如何在Java代碼中集成比特幣支持功能,例如創(chuàng)建地址、管理錢包、構(gòu)造裸交易等,是Java工程師不可多得的比特幣開發(fā)學(xué)習課程。
php比特幣開發(fā)教程,本課程面向初學(xué)者,內(nèi)容即涵蓋比特幣的核心概念,例如區(qū)塊鏈存儲、去中心化共識機制、密鑰與腳本、交易與UTXO等,同時也詳細講解如何在Php代碼中集成比特幣支持功能,例如創(chuàng)建地址、管理錢包、構(gòu)造裸交易等,是Php工程師不可多得的比特幣開發(fā)學(xué)習課程。
這里是原文以太坊區(qū)塊鏈Asp.Net Core的安全API設(shè)計
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://hztianpu.com/yun/24351.html
摘要:去中心化應(yīng)用程序的常見設(shè)計不僅依賴于以太坊區(qū)塊鏈,還依賴于層。每個用戶的所有登錄操作在以太坊區(qū)塊鏈上變得不可公開。用于驗證用戶身份的機制與以太坊用于保證以太坊區(qū)塊鏈安全性的機制相同。以太坊,主要是針對工程師使用進行區(qū)塊鏈以太坊開發(fā)的詳解。 去中心化應(yīng)用程序(DApp)的常見設(shè)計不僅依賴于以太坊區(qū)塊鏈,還依賴于API層。在這種情況下,DApp通過用戶的以太坊帳戶與智能合約進行交互,并通過...
摘要:以太坊背后的主要人物是。以太坊通過在區(qū)塊鏈上引入智能合約,徹底改變了加密世界。以太坊使用名為以太坊虛擬機的虛擬機執(zhí)行其智能合約。以太坊最終將利用協(xié)議轉(zhuǎn)向權(quán)益證明。截至目前,以太坊在可擴展性方面都失敗了。 不同的區(qū)塊鏈智能合約和區(qū)塊鏈技術(shù)現(xiàn)在風靡一時。越來越多的人出于某種原因試圖進入這個神奇的世界。如果你是這項技術(shù)的新手并正在尋找基于區(qū)塊鏈的開發(fā)平臺的快速入門,那么本指南非常適合你。我們...
摘要:最初,我對以太坊區(qū)塊鏈,智能合約和應(yīng)用程序提出了大量疑問。即使需要額外的工具來設(shè)置開發(fā)環(huán)境,現(xiàn)在微軟將使用新的針對以太坊區(qū)塊鏈產(chǎn)品。 最近區(qū)塊鏈技術(shù)引起了我的注意。我剛開始了解它,就看到了區(qū)塊鏈去中心化架構(gòu)的巨大潛力,并且它能夠簡化各種現(xiàn)有繁瑣的流程,通過各種形式的合約。 作為一名.NET開發(fā)人員,我主要使用的是一些提供中心數(shù)據(jù)源的架構(gòu),因此區(qū)塊鏈的去中心化概念對我來說是全新的。我很快...
閱讀 2126·2021-11-25 09:43
閱讀 797·2021-10-11 10:58
閱讀 1923·2019-08-30 15:55
閱讀 1871·2019-08-30 13:13
閱讀 882·2019-08-29 17:01
閱讀 1985·2019-08-29 15:30
閱讀 991·2019-08-29 13:49
閱讀 2313·2019-08-29 12:13