脚本宝典收集整理的这篇文章主要介绍了

用以太坊区块链保证Asp.Net Core的API安全(下)

脚本宝典小编觉得挺不错的,现在分享给大家,也给大家做个参考,希望能帮助你少写一行代码,多一份安全和惬意。
<p><code></p> <p>上一篇<a href="http://blog.hubwiz.com/2018/10/29/ethereum-asp_net_core_api-secure/" rel="nofollow noreferrer" target="_blank">用以太坊区块链保证Asp.Net Core的API安全(上)</a>我们介绍了基本的解决方案,这一篇我们重点来看客户端。</p> <p>正如我们所说,我们的DApp是一个简单的<a href="http://www.js-code.com/tag/html" title="HTML" target="_blank">HTML</a>/ES6客户端。我们将在Asp.Net Core 2之上构建客户端,以利用<strong>IIS Express和Visual Studio IDE</strong>。因此,<code>Startup.cs</code>类中的<code>Configure</code>方法将是:</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseDefaultFiles(); app.UseStaticFiles();" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs objectivec"><code><span class="hljs-keyword"><a href="http://www.js-code.com/tag/if" title="浏览关于“if”的文章" target="_blank" class="tag_link">if</a></span> (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseDefaultFiles(); app.UseStaticFiles();</code></pre> <p>使DApp成为<code>NPM</code>项目并安装必备条件以使用ES6 Javascript标准。这不是强制性的,可以使用自己的堆栈构建DApp。</p> <p>从项目文件夹运行<code>Powershell</code>并运行以下<code>NPM</code>命令:</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="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" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs sql"><code>npm <a href="http://www.js-code.com/tag/in" title="浏览关于“in”的文章" target="_blank" class="tag_link">in</a>it npm <span class="hljs-keyword">inst<a href="http://www.js-code.com/tag/all" title="浏览关于“all”的文章" target="_blank" class="tag_link">all</a></span> webpack npm <span class="hljs-keyword">install</span> <a href="http://www.js-code.com/tag/babel" title="浏览关于“babel”的文章" target="_blank" class="tag_link">babel</a>-core babel-loader <span class="hljs-comment">--save-dev</span> npm <span class="hljs-keyword">install</span> babel-p<a href="http://www.js-code.com/tag/reset" title="浏览关于“reset”的文章" target="_blank" class="tag_link">reset</a>-es2015 <span class="hljs-comment">--save-dev</span> npm <span class="hljs-keyword">install</span> babel-preset-stage<span class="hljs-number">-0</span> <span class="hljs-comment">--save-dev</span> npm <span class="hljs-keyword">install</span> babel-polyfill <span class="hljs-comment">--save</span> npm <span class="hljs-keyword">install</span> babel-runtime <span class="hljs-comment">--save</span> npm <span class="hljs-keyword">install</span> babel-<span class="hljs-keyword"><a href="http://www.js-code.com/tag/plugin" title="浏览关于“plugin”的文章" target="_blank" class="tag_link">plugin</a></span>-trans<a href="http://www.js-code.com/tag/form" title="浏览关于“form”的文章" target="_blank" class="tag_link">form</a>-runtime <span class="hljs-comment">--save-dev</span></code></pre> <p>要配置<code>webpack/<a href="http://www.js-code.com/tag/babel" title="babel" target="_blank">babel</a></code>,请使用以下配置创建<code>webpack.config.js</code>文件:</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="var path = require(&quot;path&quot;); module.exports = { entry: [ &quot;babel-polyfill&quot;, &quot;./src/main&quot; ], output: { publicPath: &quot;/js/&quot;, path: path.join(__dirname, &quot;/wwwroot/js/&quot;), filename: &quot;main.build.js&quot; } };" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs lua"><code><a href="http://www.js-code.com/tag/var" title="浏览关于“var”的文章" target="_blank" class="tag_link">var</a> <span class="hljs-built_in">path</span> = <span class="hljs-built_in">require</span>(<span class="hljs-string">"path"</span>); module.<a href="http://www.js-code.com/tag/export" title="浏览关于“export”的文章" target="_blank" class="tag_link">export</a>s = { en<a href="http://www.js-code.com/tag/try" title="浏览关于“try”的文章" target="_blank" class="tag_link">try</a>: [ <span class="hljs-string">"babel-polyfill"</span>, <span class="hljs-string">"./src/main"</span> ], <span class="hljs-built_in">output</span>: { <a href="http://www.js-code.com/tag/public" title="浏览关于“public”的文章" target="_blank" class="tag_link">public</a>Path: <span class="hljs-string">"/js/"</span>, <span class="hljs-built_in">path</span>: <span class="hljs-built_in">path</span>.join(__dir<a href="http://www.js-code.com/tag/name" title="浏览关于“name”的文章" target="_blank" class="tag_link">name</a>, <span class="hljs-string">"/wwwroot/js/"</span>), filename: <span class="hljs-string">"main.build.js"</span> } };</code></pre> <p>我们已设定<code>webpack</code>将<code>src/ma<a href="http://www.js-code.com/tag/in" title="in" target="_blank">in</a>.js</code>文件构建到<code>/www/js/ma<a href="http://www.js-code.com/tag/in" title="in" target="_blank">in</a>.build.js</code>。</p> <p>安装以太坊扩展包:</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="npm install web3 npm install ethereumjs-util" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs sql"><code>npm <span class="hljs-keyword">install</span> web3 npm <span class="hljs-keyword">install</span> ethereumjs-util</code></pre> <p>Web3是一个<code><a href="http://www.js-code.com/tag/java" title="java" target="_blank">java</a>script</code>封装包,它简化了针对以太坊区块链的JSON RPC调用。<code>Ethereumjs-util</code>提供了一些以太坊特定的实用程序。让我们构建一个非常简单的<a href="http://www.js-code.com/tag/html" title="HTML" target="_blank">HTML</a>页面。我们需要一个登录按钮和另一个按钮来从我们的<a href="http://www.js-code.com/tag/api" title="API" target="_blank">API</a>层加载一些安全数据:</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="<a href="http://www.js-code.com/tag/button" title="button" target="_blank">button</a>" <a href="http://www.js-code.com/tag/class" title="class" target="_blank">class</a>="copyCode code-tool" data-toggle="tooltip" data-placement="<a href="http://www.js-code.com/tag/top" title="top" target="_blank">top</a>" data-clipboard-<a href="http://www.js-code.com/tag/text" title="text" target="_blank">text</a>="<!DOCTYPE html><br /> <html><br /> <head><br /> <meta charset=&quot;utf-8&quot; /><br /> <title>Ethereum Jwt Client</title><br /> </head><br /> <body></p> <h1>Ethereum Jwt Client</h1> <div id=&quot;login-view&quot;> <label>Your account: </label> <span id=&quot;eth_account_span&quot;></span><br /> <button type=&quot;submit&quot; id=&quot;login_btn&quot;>Login</button> </div> <div id=&quot;data-view&quot;> <button type=&quot;submit&quot; id=&quot;load_data_btn&quot;>Request <a href="http://www.js-code.com/tag/secure" title="secure" target="_blank">secure</a>d data</button></p> <ul id=&quot;data_list&quot;> </ul></div> <p> <script src=&quot;js/main.build.js&quot;></script><br /> </body><br /> </html>" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs xml"><code><span class="hljs-meta">&lt;!DOCTYPE html&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">html</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr"><a href="http://www.js-code.com/tag/char" title="浏览关于“char”的文章" target="_blank" class="tag_link">char</a>set</span>=<span class="hljs-string">"utf-8"</span> /&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Ethereum Jwt Client<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span> <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Ethereum Jwt Client<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name"><a href="http://www.js-code.com/tag/div" title="浏览关于“div”的文章" target="_blank" class="tag_link">div</a></span> <span class="hljs-attr">id</span>=<span class="hljs-string">"login-view"</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">label</span>&gt;</span>Your account: <span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"eth_account_span"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name"><a href="http://www.js-code.com/tag/button" title="浏览关于“button”的文章" target="_blank" class="tag_link">button</a></span> <span class="hljs-attr">type</span>=<span class="hljs-string">"<a href="http://www.js-code.com/tag/submit" title="浏览关于“submit”的文章" target="_blank" class="tag_link">submit</a>"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"login_btn"</span>&gt;</span>Login<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span> <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"data-view"</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"load_data_btn"</span>&gt;</span>Request <a href="http://www.js-code.com/tag/secure" title="浏览关于“secure”的文章" target="_blank" class="tag_link">secure</a>d data<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"data_list"</span>&gt;</span> <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span> <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"js/main.build.js"</span>&gt;</span><span class="undefined"></span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span> <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span> <span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span></code></pre> <p>DApp逻辑将驻留在<code>src/main.js</code>文件中,正如我们在<code>webpack.config.js</code>文件中指定的那样。<code>src/main.js</code>文件将是:</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="let ethUtil = require('ethereumjs-util'); let Web3 = require('web3'); let coinbase = null; let accessToken = null; let init = () => {<br /> if (typeof web3 !== 'undefined') {<br /> web3 = new Web3(web3.currentProvider);<br /> web3.eth.getCoinbase(function (err, account) {<br /> if (err === null &amp;&amp; ethUtil.isValidAddress(account)) {<br /> coinbase = account;<br /> eth_account_span.innerHTML = coinbase;<br /> } else {<br /> eth_account_span.innerHTML = 'Please unlock your account and refresh the page';<br /> console.error(err);<br /> }<br /> });</p> <p> } else {<br /> eth_account_span.innerHTML = 'Please install or unlock Metamask browser plugin or navigate this page with Mist or another web3 browser';<br /> }<br /> };</p> <p>let request = obj => {<br /> return new Promise((resolve, reject) => {<br /> let xhr = new XMLHttpRequest();<br /> xhr.open(obj.method || &quot;GET&quot;, obj.url);<br /> if (obj.headers) {<br /> Object.keys(obj.headers).forEach(key => {<br /> xhr.setRequestHeader(key, obj.headers[key]);<br /> });<br /> }<br /> xhr.onload = () => {<br /> if (xhr.status >= 200 &amp;&amp; xhr.<a href="http://www.js-code.com/tag/status" title="status" target="_blank">status</a> < 300) { resolve(xhr.response); } else { reject(xhr.statusText); } }; xhr.onerror = () => reject(xhr.statusText);<br /> xhr.send(obj.body);<br /> });<br /> };</p> <p>login_btn.addEventListener('click', (e) => {<br /> e.preventDefault();</p> <p> login_btn.setAttribute('disabled', 'disabled');<br /> login_btn.innerHTML = 'Please sign the message';</p> <p> 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.';<br /> let msg = ethUtil.bufferToHex(new Buffer(plain, 'utf8'));<br /> let hash = ethUtil.bufferToHex(ethUtil.keccak256(&quot;x19Ethereum Signed Message:n&quot; + plain.length + plain));<br /> let from = coinbase;</p> <p> let params = [msg, from];<br /> let method = 'personal_sign';</p> <p> web3.currentProvider.sendAsync({<br /> method,<br /> params,<br /> from,<br /> }, function (err, result) {<br /> if (err || result.error) {<br /> login_btn.removeAttribute('disabled');<br /> login_btn.innerHTML = 'Login';</p> <p> console.error(err);<br /> return console.error(result.error);<br /> }<br /> console.log({<br /> 'signature': result.result,<br /> 'msg': msg,<br /> 'hash': hash<br /> });</p> <p> login_btn.innerHTML = 'Requesting token...';<br /> let loginData = {};<br /> loginData.signer = from;<br /> loginData.signature = result.result;<br /> loginData.message = msg;<br /> loginData.hash = hash;</p> <p> request({<br /> url: 'http://localhost:49443/api/token',<br /> body: JSON.stringify(loginData),<br /> method: 'post',<br /> headers: {<br /> 'Authorization': 'Bearer ' + accessToken,<br /> 'Content-type': 'application/json'<br /> }<br /> }).then(data => {<br /> var json = JSON.parse(data);<br /> accessToken = json.token;<br /> console.log('access token: ' + accessToken);</p> <p> login_btn.removeAttribute('disabled');<br /> login_btn.innerHTML = 'Login';<br /> }).catch(error => {<br /> console.error(error);</p> <p> login_btn.removeAttribute('disabled');<br /> login_btn.innerHTML = 'Login';<br /> });<br /> });<br /> });</p> <p>load_data_btn.addEventListener('click', (e) => {<br /> e.preventDefault();</p> <p> request({<br /> url: 'http://localhost:49443/api/values',<br /> headers: {<br /> 'Authorization': 'Bearer ' + accessToken<br /> }<br /> }).then(data => {<br /> <a href="http://www.js-code.com/tag/var" title="var" target="_blank">var</a> json = JSON.parse(data);<br /> <a href="http://www.js-code.com/tag/for" title="for" target="_blank">for</a> (<a href="http://www.js-code.com/tag/let" title="let" target="_blank">let</a> i = 0; i < json.<a href="http://www.js-code.com/tag/length" title="length" target="_blank">length</a>; i++) {<br /> data_list.inner<a href="http://www.js-code.com/tag/html" title="浏览关于“HTML”的文章" target="_blank" class="tag_link">HTML</a> += '</p> <li>' + json[i] + '</li> <p>';<br /> }<br /> }).catch(error => {<br /> console.error(err);<br /> });</p> <p>});</p> <p>window.addEventListener('load', init);" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs typescript"><code><span class="hljs-keyword"><a href="http://www.js-code.com/tag/let" title="浏览关于“let”的文章" target="_blank" class="tag_link">let</a></span> ethUtil = <span class="hljs-built_in">require</span>(<span class="hljs-string">'ethereumjs-util'</span>); <span class="hljs-keyword">let</span> Web3 = <span class="hljs-built_in">require</span>(<span class="hljs-string">'web3'</span>); <span class="hljs-keyword">let</span> coinbase = <span class="hljs-literal"><a href="http://www.js-code.com/tag/null" title="浏览关于“null”的文章" target="_blank" class="tag_link">null</a></span>; <span class="hljs-keyword">let</span> accessToken = <span class="hljs-literal">null</span>; <span class="hljs-keyword">let</span> init = <span class="hljs-function"><span class="hljs-params">()</span> =&gt;</span> { <span class="hljs-keyword">if</span> (<span class="hljs-keyword"><a href="http://www.js-code.com/tag/typeof" title="浏览关于“typeof”的文章" target="_blank" class="tag_link">typeof</a></span> web3 !== <span class="hljs-string">'<a href="http://www.js-code.com/tag/undefined" title="浏览关于“undefined”的文章" target="_blank" class="tag_link">undefined</a>'</span>) { web3 = <span class="hljs-keyword"><a href="http://www.js-code.com/tag/new" title="浏览关于“new”的文章" target="_blank" class="tag_link">new</a></span> Web3(web3.currentProvider); web3.eth.getCoinbase(<span class="hljs-function"><span class="hljs-keyword"><a href="http://www.js-code.com/tag/function" title="浏览关于“function”的文章" target="_blank" class="tag_link">function</a></span> (<span class="hljs-params">err, account</span>) </span>{ <span class="hljs-keyword">if</span> (err === <span class="hljs-literal">null</span> &amp;&amp; ethUtil.isValidAddress(account)) { coinbase = account; eth_account_span.innerHTML = coinbase; } <span class="hljs-keyword"><a href="http://www.js-code.com/tag/else" title="浏览关于“else”的文章" target="_blank" class="tag_link">else</a></span> { eth_account_span.innerHTML = <span class="hljs-string">'Please unlock your account and refresh the page'</span>; <span class="hljs-built_in">console</span>.error(err); } }); } <span class="hljs-keyword">else</span> { eth_account_span.innerHTML = <span class="hljs-string">'Please install or unlock Metamask browser plugin or <a href="http://www.js-code.com/tag/navigate" title="浏览关于“navigate”的文章" target="_blank" class="tag_link">navigate</a> <a href="http://www.js-code.com/tag/this" title="浏览关于“this”的文章" target="_blank" class="tag_link">this</a> page with Mist or another web3 browser'</span>; } }; <span class="hljs-keyword">let</span> request = <span class="hljs-function"><span class="hljs-params">obj</span> =&gt;</span> { <span class="hljs-keyword"><a href="http://www.js-code.com/tag/return" title="浏览关于“return”的文章" target="_blank" class="tag_link">return</a></span> <span class="hljs-keyword">new</span> <span class="hljs-built_in"><a href="http://www.js-code.com/tag/promise" title="浏览关于“Promise”的文章" target="_blank" class="tag_link">Promise</a></span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> { <span class="hljs-keyword">let</span> xhr = <span class="hljs-keyword">new</span> XMLHttpRequest(); xhr.<a href="http://www.js-code.com/tag/open" title="浏览关于“open”的文章" target="_blank" class="tag_link">open</a>(obj.method || <span class="hljs-string">"GET"</span>, obj.url); <span class="hljs-keyword">if</span> (obj.headers) { <span class="hljs-built_in"><a href="http://www.js-code.com/tag/Object" title="浏览关于“Object”的文章" target="_blank" class="tag_link">Object</a></span>.keys(obj.headers).<a href="http://www.js-code.com/tag/for" title="浏览关于“for”的文章" target="_blank" class="tag_link">for</a>Each(<span class="hljs-function"><span class="hljs-params">key</span> =&gt;</span> { xhr.setRequestHeader(key, obj.headers[key]); }); } xhr.<a href="http://www.js-code.com/tag/onload" title="浏览关于“onload”的文章" target="_blank" class="tag_link">onload</a> = <span class="hljs-function"><span class="hljs-params">()</span> =&gt;</span> { <span class="hljs-keyword">if</span> (xhr.<a href="http://www.js-code.com/tag/status" title="浏览关于“status”的文章" target="_blank" class="tag_link">status</a> &gt;= <span class="hljs-number">200</span> &amp;&amp; xhr.status &lt; <span class="hljs-number">300</span>) { resolve(xhr.response); } <span class="hljs-keyword">else</span> { reject(xhr.statusText); } }; xhr.<a href="http://www.js-code.com/tag/onerror" title="浏览关于“onerror”的文章" target="_blank" class="tag_link">onerror</a> = <span class="hljs-function"><span class="hljs-params">()</span> =&gt;</span> reject(xhr.statusText); xhr.send(obj.body); }); }; login_btn.addEventListener(<span class="hljs-string">'click'</span>, <span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> { e.pr<a href="http://www.js-code.com/tag/event" title="浏览关于“event”的文章" target="_blank" class="tag_link">event</a>Default(); login_btn.setAttribute(<span class="hljs-string">'disabled'</span>, <span class="hljs-string">'disabled'</span>); login_btn.innerHTML = <span class="hljs-string">'Please sign the message'</span>; <span class="hljs-keyword">let</span> plain = <span class="hljs-string">'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 <a href="http://www.js-code.com/tag/private" title="浏览关于“private”的文章" target="_blank" class="tag_link">private</a> key server side.'</span>; <span class="hljs-keyword">let</span> msg = ethUtil.bufferToHex(<span class="hljs-keyword">new</span> Buffer(plain, <span class="hljs-string">'utf8'</span>)); <span class="hljs-keyword">let</span> hash = ethUtil.bufferToHex(ethUtil.keccak256(<span class="hljs-string">"x19Ethereum Signed Message:n"</span> + plain.<a href="http://www.js-code.com/tag/length" title="浏览关于“length”的文章" target="_blank" class="tag_link">length</a> + plain)); <span class="hljs-keyword">let</span> <span class="hljs-keyword">from</span> = coinbase; <span class="hljs-keyword">let</span> params = [msg, <span class="hljs-keyword">from</span>]; <span class="hljs-keyword">let</span> method = <span class="hljs-string">'personal_sign'</span>; web3.currentProvider.sendAsync({ method, params, <span class="hljs-keyword">from</span>, }, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">err, result</span>) </span>{ <span class="hljs-keyword">if</span> (err || result.error) { login_btn.removeAttribute(<span class="hljs-string">'disabled'</span>); login_btn.innerHTML = <span class="hljs-string">'Login'</span>; <span class="hljs-built_in">console</span>.error(err); <span class="hljs-keyword">return</span> <span class="hljs-built_in">console</span>.error(result.error); } <span class="hljs-built_in">console</span>.log({ <span class="hljs-string">'signature'</span>: result.result, <span class="hljs-string">'msg'</span>: msg, <span class="hljs-string">'hash'</span>: hash }); login_btn.innerHTML = <span class="hljs-string">'Requesting token...'</span>; <span class="hljs-keyword">let</span> loginData = {}; loginData.signer = <span class="hljs-keyword">from</span>; loginData.signature = result.result; loginData.message = msg; loginData.hash = hash; request({ url: <span class="hljs-string">'http://localhost:49443/api/token'</span>, body: <span class="hljs-built_in">JSON</span>.stringify(loginData), method: <span class="hljs-string">'post'</span>, headers: { <span class="hljs-string">'Authorization'</span>: <span class="hljs-string">'Bearer '</span> + accessToken, <span class="hljs-string">'Content-type'</span>: <span class="hljs-string">'application/json'</span> } }).then(<span class="hljs-function"><span class="hljs-params">data</span> =&gt;</span> { <span class="hljs-keyword">var</span> json = <span class="hljs-built_in">JSON</span>.parse(data); accessToken = json.token; <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'access token: '</span> + accessToken); login_btn.removeAttribute(<span class="hljs-string">'disabled'</span>); login_btn.innerHTML = <span class="hljs-string">'Login'</span>; }).<a href="http://www.js-code.com/tag/catch" title="浏览关于“catch”的文章" target="_blank" class="tag_link">catch</a>(<span class="hljs-function"><span class="hljs-params">error</span> =&gt;</span> { <span class="hljs-built_in">console</span>.error(error); login_btn.removeAttribute(<span class="hljs-string">'disabled'</span>); login_btn.innerHTML = <span class="hljs-string">'Login'</span>; }); }); }); load_data_btn.addEventListener(<span class="hljs-string">'click'</span>, <span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> { e.preventDefault(); request({ url: <span class="hljs-string">'http://localhost:49443/api/values'</span>, headers: { <span class="hljs-string">'Authorization'</span>: <span class="hljs-string">'Bearer '</span> + accessToken } }).then(<span class="hljs-function"><span class="hljs-params">data</span> =&gt;</span> { <span class="hljs-keyword">var</span> json = <span class="hljs-built_in">JSON</span>.parse(data); <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; json.length; i++) { data_list.innerHTML += <span class="hljs-string">'&lt;li&gt;'</span> + json[i] + <span class="hljs-string">'&lt;/li&gt;'</span>; } }).catch(<span class="hljs-function"><span class="hljs-params">error</span> =&gt;</span> { <span class="hljs-built_in">console</span>.error(err); }); }); <span class="hljs-built_in"><a href="http://www.js-code.com/tag/window" title="浏览关于“window”的文章" target="_blank" class="tag_link">window</a></span>.addEventListener(<span class="hljs-string">'load'</span>, init);</code></pre> <ul> <li>1.<code>coinbase</code>和<code>accessToken</code>是全局变量,分别存储用户以太坊帐户和JWT token。</li> <li>2.<code>init</code>函数从Metamask提供的提供程序初始化web3对象,然后它尝试检索用户的帐户(coinbase)。这需要解锁在Metamask中签名的帐户。</li> <li>3.<code>require</code>函数只是hxr对象的封装,可以轻松地向<a href="http://www.js-code.com/tag/api" title="API" target="_blank">API</a>层调用ajax。</li> <li>4.<strong>load_data_btn</strong>单击处理程序对<a href="http://www.js-code.com/tag/api" title="浏览关于“API”的文章" target="_blank" class="tag_link">API</a>层安全端点进行ajax调用。这需要有效的<code>accessToken</code>才能工作,否则,API层将响应401 HTTP响应。</li> <li>5.<strong>login_btn</strong>单击是一个两步功能。首先,它要求用户签署任意消息。签名后,它会将帐户,签名,明文消息和带前缀的哈希发送到令牌端点。</li> </ul> <p>请注意,<code>web3.personal.sign</code>将十六进制格式(0x ...)的普通字符串的字节<a href="http://www.js-code.com/tag/%e6%95%b0%e7%bb%84" title="数组" target="_blank">数组</a>作为输入。</p> <p>正如我们所说的,服务器端,我们将使用两种不同的方式从签名中恢复公钥:在一个中我们将使用JSON RPC 接口中的<code>web3.personal.ecrecover</code>(web3.personal.sign对应);在另一个中,我们将使用底层的<code>ecrecover</code>离线功能。根据文档,<code>web3.personal.sign</code>使用底层签名函数来签署hash和前缀消息,因此,为了使用底层<code>ecrecover</code>对应,我们还需要计算并将此hash发送到令牌端点。</p> <p>运行两个应用程序并使用安装了Metamask插件的浏览器导航到客户端。请记住,为了将<code>src/main.js</code>文件构建到<code>js/main.build.js</code>,你需要从<code>Powershell</code>运行<code>webpac</code>命令。如果一切正常,客户端将检索<code>coinbase</code>,你将在页面上看到你的帐户:</p> <p><span class="img-wrap"><img data-src="/img/remote/1460000016859023?w=1000&amp;h=542" src="https://static.segmentfault.com/v-5cc2cd8e/global/img/squares.svg" alt="" title="" style="cursor: pointer;"></span></p> <p>如果你现在单击“请求数据”按钮,将获得HTTP响应401。如果单击“登录”按钮,Metamask将提示你签名:</p> <p><span class="img-wrap"><img data-src="/img/remote/1460000016859024" src="https://static.segmentfault.com/v-5cc2cd8e/global/img/squares.svg" alt="" title="" style="cursor: pointer;"></span></p> <p>签名后,处理程序将对令牌端点进行ajax调用。在此阶段,身份验证方法不会检查任何签名,因此端点将始终发出JWT令牌。一旦收到JWT令牌,客户端就能通过ajax调用安全端点。如果现在单击“请求数据”按钮,将收到HTTP响应200和数据负载:</p> <p><span class="img-wrap"><img data-src="/img/remote/1460000016859025" src="https://static.segmentfault.com/v-5cc2cd8e/global/img/squares.svg" alt="" title="" style="cursor: pointer;"></span></p> <h3 id="articleHeader0">从签名中检索以太坊帐户</h3> <p>到目前为止,<code>EthereumJwtApi</code>是一个简单的JWT Asp.Net核心示例,因为它不提供任何有效的身份验证方法。</p> <p><code>TokenController</code>的关键部分是两个<code>Authenticate</code>方法及其从签名中检索以太坊帐户的能力。为此,你需要安装<code>Nethereum.Web3 NuGet</code>包。Nethereum是以太坊的.Net实现。</p> <p><code>Authenticate</code>方法只是对<code>web3.personal.ecrecover</code>函数进行JSON RPC调用:</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="<a href="http://www.js-code.com/tag/button" title="button" target="_blank">button</a>" <a href="http://www.js-code.com/tag/class" title="class" target="_blank">class</a>="copyCode code-tool" data-toggle="tooltip" data-placement="<a href="http://www.js-code.com/tag/top" title="top" target="_blank">top</a>" data-clipboard-<a href="http://www.js-code.com/tag/text" title="text" target="_blank">text</a>="<a href="http://www.js-code.com/tag/private" title="private" target="_blank">private</a> async Task<UserVM> Authenticate(LoginVM login)<br /> {<br /> UserVM user = <a href="http://www.js-code.com/tag/null" title="null" target="_blank">null</a>;</p> <p> <a href="http://www.js-code.com/tag/var" title="var" target="_blank">var</a> client = <a href="http://www.js-code.com/tag/new" title="new" target="_blank">new</a> RpcClient(<a href="http://www.js-code.com/tag/new" title="new" target="_blank">new</a> Uri(_config[&quot;Nethereum:Geth&quot;])); // Require the RPC endpo<a href="http://www.js-code.com/tag/int" title="int" target="_blank">int</a> of a Geth <a href="http://www.js-code.com/tag/node" title="node" target="_blank">node</a> as input eg: http://127.0.0.1:8545<br /> var signer = await client.SendRequestAsync<string>(new RpcRequest(1, &quot;personal_ecRecover&quot;, login.Message, login.Signature));</p> <p> if (signer.ToLower().Equals(login.Signer.ToLower()))<br /> {<br /> // read user from DB or create a new one<br /> // for now we fake a new user<br /> user = new UserVM { Account = signer, Name = string.Empty, Email = string.Empty };<br /> }</p> <p> return user;<br /> }" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs cs"><code><span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">async</span> Task&lt;UserVM&gt; <span class="hljs-title">Authenticate</span>(<span class="hljs-params">LoginVM login</span>)</span> { UserVM user = <span class="hljs-literal">null</span>; <span class="hljs-keyword">var</span> client = <span class="hljs-keyword">new</span> RpcClient(<span class="hljs-keyword">new</span> Uri(_config[<span class="hljs-string">"Nethereum:Geth"</span>])); <span class="hljs-comment">// Require the RPC endpo<a href="http://www.js-code.com/tag/int" title="浏览关于“int”的文章" target="_blank" class="tag_link">int</a> of a Geth <a href="http://www.js-code.com/tag/node" title="浏览关于“node”的文章" target="_blank" class="tag_link">node</a> as input eg: http://127.0.0.1:8545</span> <span class="hljs-keyword">var</span> signer = <span class="hljs-keyword">await</span> client.SendRequestAsync&lt;<span class="hljs-keyword">string</span>&gt;(<span class="hljs-keyword">new</span> RpcRequest(<span class="hljs-number">1</span>, <span class="hljs-string">"personal_ecRecover"</span>, login.Message, login.Signature)); <span class="hljs-keyword">if</span> (signer.ToLower().Equals(login.Signer.ToLower())) { <span class="hljs-comment">// read user from DB or create a new one</span> <span class="hljs-comment">// for now we fake a new user</span> user = <span class="hljs-keyword">new</span> UserVM { Account = signer, Name = <span class="hljs-keyword">string</span>.Empty, Email = <span class="hljs-keyword">string</span>.Empty }; } <span class="hljs-keyword">return</span> user; }</code></pre> <p>PRO:</p> <p><code>web3.personal.sign</code>是<code>web3.personal.sign</code>的对应部分,因此你无需担心其底层实现。</p> <p>缺点:</p> <p>需要你自己的Geth节点。不支持Parity,Infura不允许JSON RPC调用<code>web3.personal.*</code>。<code>Authenticate2</code>方法显示了另一种方法,它使用底层<code>ecrecover</code>功能的离线实现:</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="<a href="http://www.js-code.com/tag/top" title="浏览关于“top”的文章" target="_blank" class="tag_link">top</a>" data-clipboard-<a href="http://www.js-code.com/tag/text" title="浏览关于“text”的文章" target="_blank" class="tag_link">text</a>="<a href="http://www.js-code.com/tag/private" title="private" target="_blank">private</a> async Task<UserVM> Authenticate2(LoginVM login)<br /> {<br /> UserVM user = null;</p> <p> var signer = new Nethereum.Signer.MessageSigner();<br /> var account = signer.EcRecover(login.Hash.HexToByteArray(), login.Signature);</p> <p> if (account.ToLower().Equals(login.Signer.ToLower()))<br /> {<br /> // read user from DB or create a new one<br /> // for now we fake a new user<br /> user = new UserVM { Account = account, Name = string.Empty, Email = string.Empty };<br /> }</p> <p> return user;<br /> }" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs cs"><code><span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">async</span> Task&lt;UserVM&gt; <span class="hljs-title">Authenticate2</span>(<span class="hljs-params">LoginVM login</span>)</span> { UserVM user = <span class="hljs-literal">null</span>; <span class="hljs-keyword">var</span> signer = <span class="hljs-keyword">new</span> Nethereum.Signer.MessageSigner(); <span class="hljs-keyword">var</span> account = signer.EcRecover(login.Hash.HexToByte<a href="http://www.js-code.com/tag/array" title="浏览关于“Array”的文章" target="_blank" class="tag_link">Array</a>(), login.Signature); <span class="hljs-keyword">if</span> (account.ToLower().Equals(login.Signer.ToLower())) { <span class="hljs-comment">// read user from DB or create a new one</span> <span class="hljs-comment">// for now we fake a new user</span> user = <span class="hljs-keyword">new</span> UserVM { Account = account, Name = <span class="hljs-keyword">string</span>.Empty, Email = <span class="hljs-keyword">string</span>.Empty }; } <span class="hljs-keyword">return</span> user; }</code></pre> <p>PRO:</p> <p>不需要JSON RPC调用就能工作。<code>MessageSigner.EcRecover</code>是<code>Nethereum</code>提供的离线功能。</p> <p>缺点:</p> <p>你需要处理<code>web3.personal.sign</code>实现才能正确恢复帐户。出于这个原因,在客户端,我们相应地计算了前缀消息哈希。</p> <h3 id="articleHeader1">结论</h3> <p>现在你拥有基本的知识和一个项目的骨架,可以使用以太坊保护你的Asp.Net Core 2 API。只需几点说明:</p> <p>web3 1.0.0处于测试阶段,<code>web3.personal.sign</code>实现可能会随着时间的推移而变化。请务必在你可以维护的代码库上使用这种身份验证方法。也许Infura某天决定允许<code>web3.personal.ecrecover</code> :-)</p> <p>======================================================================</p> <p>分享一些以太坊、EOS、比特币等区块链相关的交互式在线编程实战教程:</p> <blockquote> <ul> <li> <a href="http://xc.hubwiz.com/course/5b2b6e82c02e6b6a59171de2?affid=1030sf" rel="nofollow noreferrer" target="_blank">java以太坊开发教程</a>,主要是针对<a href="http://www.js-code.com/tag/java" title="java" target="_blank">java</a>和<a href="http://www.js-code.com/tag/android" title="android" target="_blank">android</a>程序员进行区块链以太坊开发的web3j详解。</li> <li> <a href="http://xc.hubwiz.com/course/5b40462cc02e6b6a59171de4?affid=1030sf" rel="nofollow noreferrer" target="_blank">python以太坊</a>,主要是针对<a href="http://www.js-code.com/tag/python" title="python" target="_blank">python</a>工程师使用web3.py进行区块链以太坊开发的详解。</li> <li> <a href="http://xc.hubwiz.com/course/5b36629bc02e6b6a59171de3?affid=1030sf" rel="nofollow noreferrer" target="_blank">php以太坊</a>,主要是介绍使用<a href="http://www.js-code.com/tag/php" title="php" target="_blank">php</a>进行智能合约开发交互,进行账号创建、交易、转账、代币开发以及过滤器和交易等内容。</li> <li> <a href="http://xc.hubwiz.com/course/5a952991adb3847553d205d1?affid=1030sf" rel="nofollow noreferrer" target="_blank">以太坊入门教程</a>,主要介绍智能合约与dapp应用开发,适合入门。</li> <li> <a href="http://xc.hubwiz.com/course/5abbb7acc02e6b6a59171dd6?affid=1030sf" rel="nofollow noreferrer" target="_blank">以太坊开发进阶教程</a>,主要是介绍使用<a href="http://www.js-code.com/tag/node" title="node" target="_blank">node</a>.js、mongodb、区块链、ipfs实现去中心化电商DApp实战,适合进阶。</li> <li> <a href="http://xc.hubwiz.com/course/5b6048c3c02e6b6a59171dee?affid=1030sf" rel="nofollow noreferrer" target="_blank">C#以太坊</a>,主要讲解如何使用C#开发基于.Net的以太坊应用,包括账户管理、状态与交易、智能合约开发与交互、过滤器和交易等。</li> <li> <a href="http://xc.hubwiz.com/course/5b52c0a2c02e6b6a59171ded?affid=1030sf" rel="nofollow noreferrer" target="_blank">EOS教程</a>,本课程帮助你快速入门EOS区块链去中心化应用的开发,内容涵盖EOS工具链、账户与钱包、发行代币、智能合约开发与部署、使用代码与智能合约交互等核心知识点,最后综合运用各知识点完成一个便签DApp的开发。</li> <li> <a href="http://xc.hubwiz.com/course/5bb35c90c02e6b6a59171df0?affid=1030sf" rel="nofollow noreferrer" target="_blank">java比特币开发教程</a>,本课程面向初学者,内容即涵盖比特币的核心概念,例如区块链存储、去中心化共识机制、密钥与脚本、交易与UTXO等,同时也详细讲解如何在Java代码中集成比特币支持功能,例如创建地址、管理钱包、构造裸交易等,是Java工程师不可多得的比特币开发学习课程。</li> <li> <a href="http://xc.hubwiz.com/course/5b9e779ac02e6b6a59171def?affid=1030sf" rel="nofollow noreferrer" target="_blank">php比特币开发教程</a>,本课程面向初学者,内容即涵盖比特币的核心概念,例如区块链存储、去中心化共识机制、密钥与脚本、交易与UTXO等,同时也详细讲解如何在Php代码中集成比特币支持功能,例如创建地址、管理钱包、构造裸交易等,是Php工程师不可多得的比特币开发学习课程。</li> </ul> </blockquote> <p>这里是原文<a href="https://medium.com/coinmonks/secure-asp-net-core-2-api-with-ethereum-blockchain-88001d5ddb6" rel="nofollow noreferrer" target="_blank">以太坊区块链Asp.Net Core的安全API设计</a></p> <p></code></p>

总结

以上是脚本宝典为你收集整理的

用以太坊区块链保证Asp.Net Core的API安全(下)

全部内容,希望文章能够帮你解决

用以太坊区块链保证Asp.Net Core的API安全(下)

所遇到的程序开发问题,欢迎加入QQ群277859234一起讨论学习。如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典网站推荐给程序员好友。 本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。

80%的人都看过