区块广播:

操作指南 | 在IPFS上构建零依赖性的应用程序·上卷

IPFS原力区版主发布在 技术文档
 4407  0

本文由IPFS原力区收集译制,版权所属原作者

注:本文由两部分组成。第一部分侧重于身份验证,第二部分侧重于从IPFS发布和获取内容。

新兴的Web 3.0技术保证了用户控制权的回归 - 不仅仅是数据,还包括互联网。曾经有一段时间,我们使用的网络并不是由寡头垄断的。这是在我们脱离了AOL这种walled-garden模式之后,我们变得自由的、可以任意连接访问、可以参与任何事情。但随后,这种情况又结束了。亚马逊、谷歌成了权力中心。Facebook决定将其命名为AOL2.0。

现在,通过分布式存储的Web技术,我们有机会收回曾经拥有的网络控制权。IPFS只是Web 3.0领域中的一个解决方案,但它让我们看到了可能出现的情况。今天,我们将构建一个简单的notes应用程序,但首先,让我们了解IPFS是什么。

IPFS(星际文件系统)希望取代HTTP协议,成为世界获取内容的方式。HTTP和IPFS的最大区别在于,Http是基于位置的,而IPFS是基于内容的。但这究竟意味着什么呢?这意味着在今天的网络中,你必须从单一来源获取内容(基于 AWS S3 bucke越来越多的公司迅速成长起来)。

IPFS是基于内容的,这意味着你可以根据其内容获取文件。你告诉IPFS网络节点,你正在查找具有确切内容的文件,并且具有该内容的网络中的第一个节点将返回该文件。许多同行可能拥有的内容比现在的网络提供更多的审查阻力,但它也提供了比今天的网络更多的容错能力。如果前面提到的s3 bucket由于任何原因变得不可访问,则无法获取内容。但是,如果保留你在IPFS上查找的内容的节点变得无法访问,则网络将继续搜索,直到可以访问保存该内容的节点。

我们可以用一整篇文章来讨论IPFS的功能以及它如何帮助web,但是已经有很多关于这方面的文章了。既然你已经对IPFS有了基本的了解,那么在开始本教程之前,还需要掌握一件事:

内容固定
将内容添加到IPFS网络时,它并不是永久性的。与90年代的旧音乐传输服务非常相似,只要对该内容有需求,IPFS网络将继续托管内容。但是,当需求下降时,这些内容可能会被垃圾收集。但是如果你需要这个文件保持可访问性,即使你是唯一一个访问它的人,即使你每年只访问一次,那又会怎样呢?

这就是内容固定发挥作用的地方。你可以自己运行IPFS节点并固定内容,但存在一些缺点。

A)新手很难做到;

B)如果你在本地计算机上运行该节点,除非该计算机始终连接到Internet,否则你将无法访问该内容;

这就是内容固定服务随着IPFS的兴起而增长的原因。Pinata就是这样一种服务。Pinata运行多个IPFS节点,并为开发人员提供一个简单的API,用于在IPFS上存储和获取内容。他们还将锁定内容以确保其可用性。

今天,我们将使用SimpleID和Pinata的组合,在IPFS上构建一个没有依赖关系的notes应用程序,开始吧。

设置
我们将使用SimpleID API在vanilla JavaScript中构建此应用程序,以使尽可能多的JavaScript框架的开发人员可以访问它。所以,你需要以下内容:

文本编辑器

让我们通过创建你的项目来设置。从终端创建一个目录,创建位置随意。我这创建在/documents/development文件夹中。

首先,创建一个目录来保存应用程序:mkdir ipfs-notes。如果你愿意,你可以给这个应用程序起个别的名字。

然后,切换到该目录:cd ipfs-notes。一旦完成,我们就准备开始了。由于我们使用可以从浏览器调用的API端点,因此无需安装任何其他内容。

现在,你需要获取SimpleID API密钥。你可以在此处注册。注册时,系统会要求你验证电子邮件地址。操作完,你就可以创建一个项目,并选择你想要包含在项目中的模块。单击“Create Project”按钮,创建名称,并提供项目URL(注意:出于安全原因,URL必须是唯一的,如果你没有,可以创建一个或提供你计划的URL最终部署)。单击“Edit Modules”按钮,然后为你的身份验证模块选择Blockstack。切换到存储模块,然后选择Pinata。点击右下方的Save,然后单击左上角的菜单并选择Account返回Account页面。

你需要做的最后一件事是获取你的开发者ID和API密钥。单击“ View Project”,你将在那里看到这两个。将它们保存在某处,我们可以准备好编码了。

启动项目
在项目文件夹的Terminal中,我们只创建一个文件:

touch index.html

在本教程中,我们将把所有JavaScript编写在一个JavaScript文件中,并index.html使用脚本标记并导入到我们的文件中。这将是一个单页应用程序,所以我们只需要一个html文件。

现在,你可以在自己喜欢的代码编辑器中打开项目,然后就可以开始编码。在index.html文件中,添加一些标准的HTML模板:


(https://appserversrc.8btc.com/post/2019091012545546649.jpg)
在项目目录的根目录中创建一个名为main.js的文件。在这个项目的整个过程中,你只有两个文件:

index.html

main.js

让我们确保一切正常。在main.js文件中,添加以下内容:

现在,打开你的index.html文件,它应该在你的浏览器中加载。打开控制台,你应该看到“testing”这个词。

现在让我们添加一些真正的代码。在我们编辑任何HTML之前,让我们处理JavaScript。从SimpleID Docs中,我们可以看到需要设置函数和初始配置。接下来,删除main.js文件中的测试代码并添加以下内容:

我们声明了一个全局变量,它是一个包含我们的配置选项的对象。在该配置对象中,包含了开发者ID和API密钥。但我们还需要告诉SimpleID我们正在使用哪些身份验证模块和存储模块(请记住:我们使用Blockstack进行身份验证,使用Pinata进行存储)。appOrigin应该与你在创建项目时生成的任何内容相匹配,并生成API密钥。scopes数组只允许你访问某些功能。

你会注意到在我们两个函数前面都有async关键字。我们提出promise的http请求,我们需要在执行其他代码之前等待promise的解析,因此我们需要使这些函数成为非同步/等待函数。你会很快明白我的意思。

现在,我们需要创建一个注册表单,并将该表单的结果传递给signUp函数。对我来说,我认为注册表单页面应该首先显示用户是否未登录,因此我将创建一个指定该页面的变量。在脚本标记之间的JavaScript代码顶部我添加了这个:

let startPage = “signup”;

这里,我们还可以创建另外两个变量。

let loggedIn = false;
let loading = false;

现在,让我们在html的body部分创建我们的注册表单:

非常基本的形式。我们稍后设置它,但是你会注意到在开头的div中有一个样式属性。为什么不显示这个表单?我们需要根据一些变量条件来显示它:

用户是否已登录?不要展示它

用户是否决定登录而不注册?不要展示它

页面加载了吗?不要展示它

如何利用我们之前创建的变量条件来呈现这个表单?在这之前,让我们创建我们的登录表单。我们可以复制注册表单并进行一些调整。你会得到这样的结果:

用户登录时,我们不需要电子邮件字段。我们还需要将元素ID更改为特定登录,而不是注册。我们还更新了要在表单提交和按钮标签上调用的函数。很简单。

现在,我们可以让我们创建的变量为我们做一些工作。我们希望这个新函数能够在每次加载页面时以及每次执行某些操作时调用更新。所以,我们这样做。在所有变量声明之后,在JavaScript代码的顶部,让我们调用一个名为pageLoad() 的函数,并在其下面创建实际函数:pageLoad();

如果保存文件并在浏览器中重新加载index.html文件,则应在控制台中看到“页面已加载”。但这不是我们想的。让我们让这段代码真正为我们工作。条件逻辑时间:

如果我们保存并重新加载页面,我们现在应该看到注册页面。但是如果用户想要登录怎么办?我们如何处理这个问题。很简单。我们可以设置几个按钮,让用户在登录和注册表单之间切换。在HTML正文部分的注册和登录表单上方,添加这些按钮,用div包装,我们可以根据需要隐藏和显示:

然后我们可以在pageload函数下面创建另一个名为changeform的函数。

有很多不同的方法可以解决这个问题,这是一个非常简单的解决方案,我将继续下去。如果你愿意,欢迎你使用不同的方法。

我们应该在html的主体中添加更多的有条件呈现的部分。我们需要一个用于加载屏幕,一个用于存放登录用户的应用程序屏幕。我们可以简单地模拟一下:

接下来我们需要做的是更新我们的pageLoad函数,并在我们更新应用程序状态时随时调用它。该功能现在应该如下所示:

现在,我们已准备好注册并登录,开始吧。你之前已经创建了配置对象。所以现在我们只需要捕获用户的注册凭据。

有几种方法可以做到这一点,为了使它尽可能简单,我们将只获取输入值。在你的signUp功能中,添加:

这只是我们最终向SimpleID API提出发布请求的开始。我们将加载变量转变为true,并捕获注册表单的输入字段。在将输入元素捕获为变量后,你会注意到我们调用了pageload()函数。这只是一个安全措施,因为我们正在更新页面状态以显示加载屏幕,而不是表单。我们希望确保已存储用户名、密码和电子邮件并准备好使用。

我要花点时间指出,我没有对这些输入元素进行任何验证。这超出了本教程的范围,但你可以这样做。

我们还存储了两个SimpleID API端点作为变量。实际上需要这两个用于创建帐户。第一个创建用户的密钥链(用户信息,私钥等)。第二个返回用于构建用户会话的必要的特定于应用程序的信息。

现在,在继续执行signUp()函数代码之前,我们应该设置HTTP请求代码。我们将在需要向SimpleID API发出请求时调用此函数,并承诺结果。所以继续创建一个名为postToApi()的新函数:

根据SimpleID API文档,我们知道正在发送表单数据,以便设置内容类型。你可能已经注意到,在前面的注册函数中,我们捕获了一个名为data的变量,该变量具有urlencoded格式,我们需要将此表单数据传递给API。

确保用在SimpleID中创建项目时收到的API密钥替换API Key。

因为我们已经将此作为承诺,所以当承诺结算时,响应将被发回。所以现在,我们可以在我们signUp之前编写的代码下面的函数中执行此操作:

实际上,你可以保存此文件,并使用我们编写的代码测试你的注册表单。但它要做的就是返回一个身份地址,这个地址本身并不是很有用。请记住,我们还需要调用第二个SimpleID API端点。但是,只有当我们收到的密钥链值不是错误时,我们才应该这样做。在console.log(keychain)下面添加以下内容:

好吧,看来这里发生了很多事,但也没那么糟。我们是说,如果第一个api调用没有错误,我们就开始第二个api调用。根据SimpleID文档,我们需要提供devID用户的用户名,用户密码,应用程序url和配置文件对象。让我们快速讨论一下profile对象。

SimpleID支持多种Web 3.0协议,其中一种协议是Blockstack。Blockstack具有此配置文件概念,允许用户相互交互并共享数据。我们希望确保始终有一个配置文件对象,确保你作为开发人员决定构建使用Blockstack存储的应用程序,或者如果用户决定使用另一个也实现了SimpleID的应用程序。请参阅,用户可以在多个应用中使用相同的帐户凭据。因此,只需知道配置文件格式(如SimpleID 文档中所述)采用上述形式。当然,我们必须对其进行uriencode,以支持表单数据post到API。
url变量和你提供给profile对象的url必须是格式正确的url,因此如果你在没有Web服务器的情况下进行开发,则不能只使用window.location.origin。如果是这种情况,你应该提供一个源代码,比如http://localhost:3000或你计划将应用程序部署到的最终url。

你可能还注意到,在我们发送给API的数据中,有一个用于开发的标志。在生产中,要确保始终如此。

在else语句中,如果第一个API调用失败,我们希望将应用程序状态转回登录屏幕,并在控制台日志中记录某种消息。如果一切都成功了,并且我们调用了第二个API端点,我们需要在该端点上嵌套一些额外的逻辑来支持成功和失败。在console.log(userdata)下面添加以下内容:

这里我们要说的是,如果第二个api调用成功,让我们解析响应(这是API返回的字符串)。然后我们想要将用户的用户名添加到我们现在创建的对象中(因为API不返回用户名)。完成后,我们需要一种方法来持久化用户的登录会话。有不同的方法来处理这个问题,对于应该在本地存储中存储哪种类型的数据存在争议。学习这些主题,但是为了本教程的目的,我将把会话信息放到本地存储中。

我们还需要翻转状态变量,并通过调用pageload()更新应用程序状态。当然,如果第二个api调用失败,用户将不会登录,我们需要将它们返回到注册屏幕。

如果你保存此项,你可以继续注册帐户。这里要注意的一点是,如果你只是在浏览器中打开index.html文件,而不是运行本地Web服务器,那么你将需要像这样的CORS扩展。原因是API端点希望基于浏览器的请求具有格式良好的源。不接受以file://开头的源。但是如果你使用cors扩展,你就可以进行开发了。

如果一切顺利,你就可以注册,你会看到你的注册表单消失,一个加载指示弹出,然后,我们之前用作占位符的“This is the app”会出现。

ok,但还有两件事我们需要做。其一,如果用户刷新页面会发生什么?试试吧。用户似乎会自动注销?此外,用户如何登录?我们还没有接通登录功能。

我们迅速处理会话的持续性。在main.js的pageLoad()函数下的文件中,我们只需要快速检查本地存储以获取用户的会话信息。如果你按照我上面的代码操作,你可以将它添加到pageLoad()函数的顶部:

就这么简单!

最后,我们要支持登录和注销。这将比设置登录代码容易得多。为了登录,我们要复制一半的注册码。我们现在就开始吧。在signup()函数下,添加以下内容:

这段代码与注册代码做了同样的事情,只是它跳过了第一个API调用。因此,如果你仍在注册页面上,请单击屏幕顶部的登录按钮,输入之前用于注册的凭据,你将看到要加载的页面更新,然后看到“This is the app”。

现在,因为我们已经持久化了用户会话,所以你应该能够刷新页面,用户仍然会保持登录状态。如果这是应该的,我们只有最后一件事要做。我们需要让用户注销。

回到你的html文件,找到我们写的应用程序代码的“This is the app”。让我们在文本上方添加一个表示“注销”的按钮。

现在,回到main.js文件中,我们可以添加如下的signOut()函数(非常简单):

保存,刷新页面,然后单击“注销”,OK。

你刚刚构建了一个无依赖关系(去中心)的页面应用程序,允许用户注册,登录和注销。在第二部分中,你将添加IPFS功能,添加一些样式,并将其变成真正的应用程序。

—未完待续—

本文由IPFS原力区编译,原文链接:https://medium.com/simpleid-dev-tools/tutorial-build-an-encrypted-notes-app-on-ipfs-part-i-39fb06fa95ce

【IPFS原力区】

价值观:价值 共建 共享 荣耀

总部位于上海,聚集基于分布式网络&存储的众多技术大咖和爱好者,深耕基于 IPFS的商业生态建设和社区发展。

每周二举办“分布式存储网络”主题沙龙,聚集了众多技术大咖和 IPFS 爱好者,通过持续输出全面、精细、优质的IPFS咨询和技术支持,将生态中的爱好者转化为IPFS支持者和参与者,共建IPFS生态的健康发展。

  • 正序
  • 最新
沙发,很寂寞......
登录 账号发表你的看法,还没有账号?立即免费 注册
帖子数 284 获赞数 3
总部位于上海,深耕 IPFS / Filecoin 社区发展与商业生态建设。秉持价值、共建、共享、荣耀的文化理念,以分布式存储服务成为行业的基石为使命,构建和成为Web 3.0 的基础设施。
推荐节点
热帖榜
热门跟帖