以太坊区块链 Asp.Net Core的安全API设计 (上)
去中心化应用程序(DApp)的常见设计不仅依赖于以太坊区块链,还依赖于API层。在这种情况下,DApp通过用户的以太坊帐户与智能合约进行交互,并通过交换用户凭据而发布的JWT token与API层进行交互。
目标是使用以太坊帐户作为用户凭据来请求JWT Token。
最简单的方法可能是请求用户使用其他随机生成的数据在以太坊上进行交易,然后在发出JWT之前检查交易和随机数据。这种方法有几个副作用:
- 1.用户必须进行交易并支付gas以进行简单的身份验证。
- 2.用户必须等待12-120秒(基于耗费的gas)才能完成身份验证过程。
- 3.每个用户的所有登录操作在以太坊区块链上变得不可公开。
这种方式不实用,并且有一些用户体验限制,我们需要一种方法让用户证明他拥有与他想要用来登录的帐户相关的私钥,而不是只(当然)要求私钥,而不管他是否进行交易。
解决方案
Metamask团队成员Dan Finlay的这篇文章向我启发了本教程。基本上,你的DApp可以提示用户使用他的私钥对短信进行签名。此签名操作不会生成交易,并且它由Metamask附加组件透明地处理(顺便说一句,你的帐户需要解锁)。签名后,帐户,消息和签名将发送到API Token endpoint。验证方法首先通过接受签名和明文消息作为输入的函数从签名中推断帐户(也称为公钥)。如果计算的以太坊地址等于用户提供的帐户,则为该帐户发出JWT Token。
请务必注意,整个身份验证流程不需要用户名/密码或OAuth外部服务。用于验证用户身份的机制与以太坊用于保证以太坊区块链安全性的机制相同。这要归功于Go ethereum(Geth)通过Metamask插件提供JSON RPC中的web3.personal.sign
。
服务器端调用对应的JSON RPC以从签名中检索帐户:web3.personal.ecrecover
。在本教程中,我们将构建一个Asp.Net Core 2项目作为API层,并构建一个简单的HTML/javascript客户端作为DApp,以实际演示此身份验证过程。
- 1.从DApp用户单击登录按钮。这需要Metamask提供的web3对象。
- 2.Metamask要求用户通过JSON RPC的
web3.personal.sign
签署消息。 - 3.签名将发送到API层,该层通过JSON RPC的
web3.personal.ecrecover
验证帐户。 - 4.验证后,API层将发布JWT。
先决条件
- 1.为Chrome或Firefox安装Metamask插件。这个附加组件“将以太坊带到你的浏览器上”。实际上,Metamask提供了一个web3对象,用于与你的DApp中的以太坊区块链进行交互,处理你的私钥并在浏览器中管理交易。
- 2.可选的。运行Geth节点。我将向你展示两种从签名中恢复以太坊帐户的方法,其中一种方法需要你的API层针对Geth节点调用JSON RPC。注意:Infura现在还不行,因为它们不允许大多数
web3.personal.*
的JSON RPC接口。出于开发目的,运行Geth节点非常简单。在生产环境中,出于安全考虑,运行Geth节点并不是一项简单的任务。最好的方法是依靠AWS或Azure提供的区块链即服务堆栈(BaaS)。 - 3.开发堆栈:Visual Studio 2017和节点包管理器(NPM)。
- 4.以太坊/Asp.Net核心/前端开发的基础知识,JWT认证流程的基础知识。
开始
打开Visual Studio 2017,创建EthereumJwtSolution
并添加两个Asp.Net Core 2 Web应用程序项目:EthereumJwtApi
和EthereumJwtClient
。为两个项目选择空项目脚手架。
EthereumJwtClient
只是一个HTML/Javascript客户端。我们将在Asp.Net Core上构建客户端应用程序,只是为了在IIS Express上轻松运行它。
我们需要准备EthereumJwtApi
来创建和处理JWT token,以保护一些安全端点。任务很简单,因为Asp.Net Core 2有一个内置的JWT机制,可以插入我们的应用程序。 打开Startup.cs并修改ConfigureServices
方法:
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options => { options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = true, ValidateAudience = true, ValidateLifetime = true, ValidateIssuerSigningKey = true, ValidIssuer = Configuration["Jwt:Issuer"], ValidAudience = Configuration["Jwt:Audience"], IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Jwt:Key"])) }; }); services.AddCors(options => { options.AddPolicy("CorsPolicy", builder => builder.AllowAnyOrigin() .AllowAnyMethod() .AllowAnyHeader() .AllowCredentials() .Build()); }); services.AddMvc();
然后修改Configure
方法:
if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseCors("CorsPolicy"); app.UseAuthentication(); app.UseMvc();
我们告诉我们的API应用程序使用JWT身份验证服务。为了与我们的用户合作,我们还需要配置Cors策略。我们在appsetting.json
中定义设置JWT配置:
"Jwt": { "Key": "averysecretpassphrase", // A random and secure passhphrase "Issuer": "http://localhost:49443/", // This API base URI "Audience": "http://localhost:51149/" // The client base URI },
为测试目的创建一个简单的可能安全端点:
[Route("api/[controller]")] public class ValuesController : Controller { // GET api/values [HttpGet, Authorize] public IEnumerable<string> Get() { return new string[] { "Secret 1", "Secret 2" }; } }
TokenController.cs
将处理JWT请求和相关的token问题:
[Route("api/[controller]")] public class TokenController : Controller { private IConfiguration _config; public TokenController(IConfiguration config) { _config = config; } [AllowAnonymous] [HttpPost] public async Task<IActionResult> CreateToken([FromBody]LoginVM login) { var user = await Authenticate(login); if (user != null) { var tokenString = BuildToken(user); return Ok(new { token = tokenString }); } return Unauthorized(); } private string BuildToken(UserVM user) { var claims = new[] { new Claim(JwtRegisteredClaimNames.Sub, user.Account), new Claim(JwtRegisteredClaimNames.GivenName, user.Name), new Claim(JwtRegisteredClaimNames.Email, user.Email), new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()) }; var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Jwt:Key"])); var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); var token = new JwtSecurityToken(_config["Jwt:Issuer"], _config["Jwt:Audience"], claims, expires: DateTime.Now.AddMinutes(30), signingCredentials: creds); return new JwtSecurityTokenHandler().WriteToken(token); } private async Task<UserVM> Authenticate(LoginVM login) { // TODO: this method will authenticate the user recovering the Ethereum address from signature using the Geth RPC web3.personal.ecrecover API UserVM user = user = new UserVM { Account = login.Account, Name = string.Empty, Email = string.Empty }; return user; } private async Task<UserVM> Authenticate2(LoginVM login) { // TODO: This method will authenticate the user recovering his Ethereum address through underlaying offline ecrecover method. UserVM user = user = new UserVM { Account = login.Account, Name = string.Empty, Email = string.Empty }; return user; }
这是一个典型的JWT控制器,核心方法,Authenticate
和Authenticate2
尚未实现。一旦实现,他们将完成相同的工作:从签名中恢复以太坊地址,并检查它是否等于客户端提供的以太坊地址。
LoginVM
表示客户端提供的用户凭据,UserVM
表示“服务器端”登录用户:
public class LoginVM { public string Signer { get; set; } // Ethereum account that claim the signature public string Signature { get; set; } // The signature public string Message { get; set; } // The plain message public string Hash { get; set; } // The prefixed and sha3 hashed message } public class UserVM { public string Account { get; set; } // Unique account name (the Ethereum account) public string Name { get; set; } // The user name public string Email { get; set; } // The user Email }
Authenticate
方法将Signature
和Message
属性作为ecRecover
函数的输入,Authenticate2
方法将采用Signature
和Hash
属性。我稍后会解释其中的差异。
======================================================================
分享一些以太坊、EOS、比特币等区块链相关的交互式在线编程实战教程:
- java以太坊开发教程,主要是针对java和android程序员进行区块链以太坊开发的web3j详解。
- python以太坊,主要是针对python工程师使用web3.py进行区块链以太坊开发的详解。
- php以太坊,主要是介绍使用php进行智能合约开发交互,进行账号创建、交易、转账、代币开发以及过滤器和交易等内容。
- 以太坊入门教程,主要介绍智能合约与dapp应用开发,适合入门。
- 以太坊开发进阶教程,主要是介绍使用node.js、mongodb、区块链、ipfs实现去中心化电商DApp实战,适合进阶。
- C#以太坊,主要讲解如何使用C#开发基于.Net的以太坊应用,包括账户管理、状态与交易、智能合约开发与交互、过滤器和交易等。
- EOS教程,本课程帮助你快速入门EOS区块链去中心化应用的开发,内容涵盖EOS工具链、账户与钱包、发行代币、智能合约开发与部署、使用代码与智能合约交互等核心知识点,最后综合运用各知识点完成一个便签DApp的开发。
- java比特币开发教程,本课程面向初学者,内容即涵盖比特币的核心概念,例如区块链存储、去中心化共识机制、密钥与脚本、交易与UTXO等,同时也详细讲解如何在Java代码中集成比特币支持功能,例如创建地址、管理钱包、构造裸交易等,是Java工程师不可多得的比特币开发学习课程。
- php比特币开发教程,本课程面向初学者,内容即涵盖比特币的核心概念,例如区块链存储、去中心化共识机制、密钥与脚本、交易与UTXO等,同时也详细讲解如何在Php代码中集成比特币支持功能,例如创建地址、管理钱包、构造裸交易等,是Php工程师不可多得的比特币开发学习课程。
汇智网原创翻译,转载请标明出处。这里是以太坊 区块链 Asp.Net Core API
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
一文上手 Elasticsearch常用可视化管理工具
本文共 674字,阅读大约需要 2分钟 ! 概 述 强大的搜索引擎 Elasticsearch 与传统关系型数据库的一个明显不同点在于 前者是一个非结构化的 NoSQL数据库,因此里面的很多概念诸如索引、类型、文档等对于初学者可能会有些疑惑。有时候我们即使搭建好了ES集群,但数据存进去后到底是以一个什么形态存在,我们可能也疑惑重重,此时要是有个可视化的管理工具来辅助一下就便易于理解了,因此本文就搜罗了几种 Elasticsearch可视化管理工具并一一体验一番。 注: 本文首发于 My Personal Blog:CodeSheep·程序羊,欢迎光临 小站 本文内容脑图如下: elasticsearch-head 项目地址:https://github.com/mobz/elasticsearch-head 直接安装方式:此处不赘述,在我的前文《CentOS-7上Elasticsearch安装填坑记》中已经记录过,可以 前去查看 Docker安装方式: docker run -d -p 9100:9100 docker.io/mobz/elasticsearch-head:5 启动访问...
- 下一篇
helm 部署和简单使用
微服务和容器化给复杂应用部署与管理带来了极大的挑战。Helm是目前Kubernetes服务编排领域的唯一开源子项目,做为Kubernetes应用的一个包管理工具,可理解为Kubernetes的apt-get / yum,由Deis 公司发起,该公司已经被微软收购。 Helm通过软件打包的形式,支持发布的版本管理和控制,很大程度上简化了Kubernetes应用部署和管理的复杂性。 随着业务容器化与向微服务架构转变,通过分解巨大的单体应用为多个服务的方式,分解了单体应用的复杂性,使每个微服务都可以独立部署和扩展,实现了敏捷开发和快速迭代和部署。但任何事情都有两面性,虽然微服务给我们带来了很多便利,但由于应用被拆分成多个组件,导致服务数量大幅增加,对于Kubernetest编排来说,每个组件有自己的资源文件,并且可以独立的部署与伸缩,这给采用Kubernetes做应用编排带来了诸多挑战: 管理、编辑与更新大量的K8s配置文件 部署一个含有大量配置文件的复杂K8s应用 分享和复用K8s配置和应用 参数化配置模板支持多个环境 管理应用的发布:回滚、diff和查看发布历史 控制一个部署周期中的某一...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS关闭SELinux安全模块
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- CentOS7安装Docker,走上虚拟化容器引擎之路
- SpringBoot2初体验,简单认识spring boot2并且搭建基础工程
- CentOS7,8上快速安装Gitea,搭建Git服务器
- Linux系统CentOS6、CentOS7手动修改IP地址
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- MySQL8.0.19开启GTID主从同步CentOS8
- Red5直播服务器,属于Java语言的直播服务器