mirror of
https://github.com/LCTT/TranslateProject.git
synced 2025-01-25 23:11:02 +08:00
commit
15f56f0357
@ -1,167 +0,0 @@
|
||||
Translating by qhwdw
|
||||
Token ERC Comparison for Fungible Tokens – Blockchainers
|
||||
======
|
||||
“The good thing about standards is that there are so many to choose from.” [_Andrew S. Tanenbaum_][1]
|
||||
|
||||
### Current State of Token Standards
|
||||
|
||||
The current state of Token standards on the Ethereum platform is surprisingly simple: ERC-20 Token Standard is the only accepted and adopted (as [EIP-20][2]) standard for a Token interface.
|
||||
|
||||
Proposed in 2015, it has finally been accepted at the end of 2017.
|
||||
|
||||
In the meantime, many Ethereum Requests for Comments (ERC) have been proposed which address shortcomings of the ERC-20, which partly were caused by changes in the Ethereum platform itself, eg. the fix for the re-entrancy bug with [EIP-150][3]. Other ERC propose enhancements to the ERC-20 Token model. These enhancements were identified by experiences gathered due to the broad adoption of the Ethereum blockchain and the ERC-20 Token standard. The actual usage of the ERC-20 Token interface resulted in new demands and requirements to address non-functional requirements like permissioning and operations.
|
||||
|
||||
This blogpost should give a superficial, but complete, overview of all proposals for Token(-like) standards on the Ethereum platform. This comparison tries to be objective but most certainly will fail in doing so.
|
||||
|
||||
### The Mother of all Token Standards: ERC-20
|
||||
|
||||
There are dozens of [very good][4] and detailed description of the ERC-20, which will not be repeated here. Just the core concepts relevant for comparing the proposals are mentioned in this post.
|
||||
|
||||
#### The Withdraw Pattern
|
||||
|
||||
Users trying to understand the ERC-20 interface and especially the usage pattern for _transfer_ ing Tokens _from_ one externally owned account (EOA), ie. an end-user (“Alice”), to a smart contract, have a hard time getting the approve/transferFrom pattern right.
|
||||
|
||||
![][5]
|
||||
|
||||
From a software engineering perspective, this withdraw pattern is very similar to the [Hollywood principle][6] (“Don’t call us, we’ll call you!”). The idea is that the call chain is reversed: during the ERC-20 Token transfer, the Token doesn’t call the contract, but the contract does the call transferFrom on the Token.
|
||||
|
||||
While the Hollywood Principle is often used to implement Separation-of-Concerns (SoC), in Ethereum it is a security pattern to avoid having the Token contract to call an unknown function on an external contract. This behaviour was necessary due to the [Call Depth Attack][7] until [EIP-150][3] was activated. After this hard fork, the re-entrancy bug was not possible anymore and the withdraw pattern did not provide any more security than calling the Token directly.
|
||||
|
||||
But why should it be a problem now, the usage might be somehow clumsy, but we can fix this in the DApp frontend, right?
|
||||
|
||||
So, let’s see what happens if a user used transfer to send Tokens to a smart contract. Alice calls transfer on the Token contract with the contract address
|
||||
|
||||
**….aaaaand it’s gone!**
|
||||
|
||||
That’s right, the Tokens are gone. Most likely, nobody will ever get the Tokens back. But Alice is not alone, as Dexaran, inventor of ERC-223, found out, about $400.000 in tokens (let’s just say _a lot_ due to the high volatility of ETH) are irretrievably lost for all of us due to users accidentally sending Tokens to smart contracts.
|
||||
|
||||
Even if the contract developer was extremely user friendly and altruistic, he couldn’t create the contract so that it could react to getting Tokens transferred to it and eg. return them, as the contract will never be notified of this transfer and the event is only emitted on the Token contract.
|
||||
|
||||
From a software engineering perspective that’s a severe shortcoming of ERC-20. If an event occurs (and for the sake of simplicity, we are now assuming Ethereum transactions are actually events), there should be a notification to the parties involved. However, there is an event, but it’s triggered in the Token smart contract which the receiving contract cannot know.
|
||||
|
||||
Currently, it’s not possible to prevent users sending Tokens to smart contracts and losing them forever using the unintuitive transfer on the ERC-20 Token contract.
|
||||
|
||||
### The Empire Strikes Back: ERC-223
|
||||
|
||||
The first attempt at fixing the problems of ERC-20 was proposed by [Dexaran][8]. The main issue solved by this proposal is the different handling of EOA and smart contract accounts.
|
||||
|
||||
The compelling strategy is to reverse the calling chain (and with [EIP-150][3] solved this is now possible) and use a pre-defined callback (tokenFallback) on the receiving smart contract. If this callback is not implemented, the transfer will fail (costing all gas for the sender, a common criticism for ERC-223).
|
||||
|
||||
![][9]
|
||||
|
||||
#### Pros:
|
||||
|
||||
* Establishes a new interface, intentionally being not compliant to ERC-20 with respect to the deprecated functions
|
||||
|
||||
* Allows contract developers to handle incoming tokens (eg. accept/reject) since event pattern is followed
|
||||
|
||||
* Uses one transaction instead of two (transfer vs. approve/transferFrom) and thus saves gas and Blockchain storage
|
||||
|
||||
|
||||
|
||||
|
||||
#### Cons:
|
||||
|
||||
* If tokenFallback doesn’t exist then the contract fallback function is executed, this might have unintended side-effects
|
||||
|
||||
* If contracts assume that transfer works with Tokens, eg. for sending Tokens to specific contracts like multi-sig wallets, this would fail with ERC-223 Tokens, making it impossible to move them (ie. they are lost)
|
||||
|
||||
|
||||
### The Pragmatic Programmer: ERC-677
|
||||
|
||||
The [ERC-667 transferAndCall Token Standard][10] tries to marriage the ERC-20 and ERC-223. The idea is to introduce a transferAndCall function to the ERC-20, but keep the standard as is. ERC-223 intentionally is not completely backwards compatible, since the approve/allowance pattern is not needed anymore and was therefore removed.
|
||||
|
||||
The main goal of ERC-667 is backward compatibility, providing a safe way for new contracts to transfer tokens to external contracts.
|
||||
|
||||
![][11]
|
||||
|
||||
#### Pros:
|
||||
|
||||
* Easy to adapt for new Tokens
|
||||
|
||||
* Compatible to ERC-20
|
||||
|
||||
* Adapter for ERC-20 to use ERC-20 safely
|
||||
|
||||
#### Cons:
|
||||
|
||||
* No real innovations. A compromise of ERC-20 and ERC-223
|
||||
|
||||
* Current implementation [is not finished][12]
|
||||
|
||||
|
||||
### The Reunion: ERC-777
|
||||
|
||||
[ERC-777 A New Advanced Token Standard][13] was introduced to establish an evolved Token standard which learned from misconceptions like approve() with a value and the aforementioned send-tokens-to-contract-issue.
|
||||
|
||||
Additionally, the ERC-777 uses the new standard [ERC-820: Pseudo-introspection using a registry contract][14] which allows for registering meta-data for contracts to provide a simple type of introspection. This allows for backwards compatibility and other functionality extensions, depending on the ITokenRecipient returned by a EIP-820 lookup on the to address, and the functions implemented by the target contract.
|
||||
|
||||
ERC-777 adds a lot of learnings from using ERC-20 Tokens, eg. white-listed operators, providing Ether-compliant interfaces with send(…), using the ERC-820 to override and adapt functionality for backwards compatibility.
|
||||
|
||||
![][15]
|
||||
|
||||
#### Pros:
|
||||
|
||||
* Well thought and evolved interface for tokens, learnings from ERC-20 usage
|
||||
|
||||
* Uses the new standard request ERC-820 for introspection, allowing for added functionality
|
||||
|
||||
* White-listed operators are very useful and are more necessary than approve/allowance , which was often left infinite
|
||||
|
||||
|
||||
#### Cons:
|
||||
|
||||
* Is just starting, complex construction with dependent contract calls
|
||||
|
||||
* Dependencies raise the probability of security issues: first security issues have been [identified (and solved)][16] not in the ERC-777, but in the even newer ERC-820
|
||||
|
||||
|
||||
|
||||
|
||||
### (Pure Subjective) Conclusion
|
||||
|
||||
For now, if you want to go with the “industry standard” you have to choose ERC-20. It is widely supported and well understood. However, it has its flaws, the biggest one being the risk of non-professional users actually losing money due to design and specification issues. ERC-223 is a very good and theoretically founded answer for the issues in ERC-20 and should be considered a good alternative standard. Implementing both interfaces in a new token is not complicated and allows for reduced gas usage.
|
||||
|
||||
A pragmatic solution to the event and money loss problem is ERC-677, however it doesn’t offer enough innovation to establish itself as a standard. It could however be a good candidate for an ERC-20 2.0.
|
||||
|
||||
ERC-777 is an advanced token standard which should be the legitimate successor to ERC-20, it offers great concepts which are needed on the matured Ethereum platform, like white-listed operators, and allows for extension in an elegant way. Due to its complexity and dependency on other new standards, it will take time till the first ERC-777 tokens will be on the Mainnet.
|
||||
|
||||
### Links
|
||||
|
||||
[1] Security Issues with approve/transferFrom-Pattern in ERC-20: <https://drive.google.com/file/d/0ByMtMw2hul0EN3NCaVFHSFdxRzA/view>
|
||||
|
||||
[2] No Event Handling in ERC-20: <https://docs.google.com/document/d/1Feh5sP6oQL1-1NHi-X1dbgT3ch2WdhbXRevDN681Jv4>
|
||||
|
||||
[3] Statement for ERC-20 failures and history: <https://github.com/ethereum/EIPs/issues/223#issuecomment-317979258>
|
||||
|
||||
[4] List of differences ERC-20/223: <https://ethereum.stackexchange.com/questions/17054/erc20-vs-erc223-list-of-differences>
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: http://blockchainers.org/index.php/2018/02/08/token-erc-comparison-for-fungible-tokens/
|
||||
|
||||
作者:[Alexander Culum][a]
|
||||
选题:[lujun9972](https://github.com/lujun9972)
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:http://blockchainers.org/index.php/author/alex/
|
||||
[1]:https://www.goodreads.com/quotes/589703-the-good-thing-about-standards-is-that-there-are-so
|
||||
[2]:https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md
|
||||
[3]:https://github.com/ethereum/EIPs/blob/master/EIPS/eip-150.md
|
||||
[4]:https://medium.com/@jgm.orinoco/understanding-erc-20-token-contracts-a809a7310aa5
|
||||
[5]:http://blockchainers.org/wp-content/uploads/2018/02/ERC-20-Token-Transfer-2.png
|
||||
[6]:http://matthewtmead.com/blog/hollywood-principle-dont-call-us-well-call-you-4/
|
||||
[7]:https://consensys.github.io/smart-contract-best-practices/known_attacks/
|
||||
[8]:https://github.com/Dexaran
|
||||
[9]:http://blockchainers.org/wp-content/uploads/2018/02/ERC-223-Token-Transfer-1.png
|
||||
[10]:https://github.com/ethereum/EIPs/issues/677
|
||||
[11]:http://blockchainers.org/wp-content/uploads/2018/02/ERC-677-Token-Transfer.png
|
||||
[12]:https://github.com/ethereum/EIPs/issues/677#issuecomment-353871138
|
||||
[13]:https://github.com/ethereum/EIPs/issues/777
|
||||
[14]:https://github.com/ethereum/EIPs/issues/820
|
||||
[15]:http://blockchainers.org/wp-content/uploads/2018/02/ERC-777-Token-Transfer.png
|
||||
[16]:https://github.com/ethereum/EIPs/issues/820#issuecomment-362049573
|
@ -0,0 +1,165 @@
|
||||
对可互换通证的通证 ERC 的比较 – Blockchainers
|
||||
======
|
||||
“对于标准来说,最好的事情莫过于大量的人都去选择使用它。“ [_Andrew S. Tanenbaum_][1]
|
||||
|
||||
### 通证标准的现状
|
||||
|
||||
在以太坊平台上,通证标准的现状出奇的简单:ERC-20 通证标准是通证接口中唯一被采用( [EIP-20][2])和接受的通证标准。
|
||||
|
||||
它在 2015 年被提出,最终接受是在 2017 年末。
|
||||
|
||||
在此期间,提出了许多解决 ERC-20 缺点的以太坊意见征集(ERC),其中的一部分是因为以太坊平台自身变更所导致的,比如,由 [EIP-150][3] 修复的重入(re-entrancy) bug。其它 ERC 提出的对 ERC-20 通证模型的强化。这些强化是通过采集大量的以太坊区块链和 ERC-20 通证标准的使用经验所确定的。ERC-20 通证接口的实际应用产生了新的要求和需要,比如像权限和操作方面的非功能性需求。
|
||||
|
||||
这篇文章将浅显但完整地对以太坊平台上提出的所有通证(类)标准进行简单概述。我将尽可能客观地去做比较,但不可避免地仍有一些不客观的地方。
|
||||
|
||||
### 通证标准之母:ERC-20
|
||||
|
||||
有成打的 [非常好的][4] 关于 ERC-20 的详细描述,在这里就不一一列出了。只对在文章中提到的相关核心概念做个比较。
|
||||
|
||||
#### 提取模式
|
||||
|
||||
用户们尽可能地去理解 ERC-20 接口,尤其是从一个外部所有者帐户(EOA)_转账_ 通证的模式,即一个终端用户(“Alice”)到一个智能合约,很难去获得 approve/transferFrom 模式权利。
|
||||
|
||||
![][5]
|
||||
|
||||
从软件工程师的角度看,这个提取模式非常类似于 [好莱坞原则][6] (“不要给我们打电话,我们会给你打电话的!”)。那个调用链的创意正好相反:在 ERC-20 通证转账中,通证不能调用合约,但是合约可以调用通证上的 `transferFrom`。
|
||||
|
||||
虽然好莱坞原则经常用于去实现关注点分离(SoC),但在以太坊中它是一个安全模式,目的是为了防止通证合约去调用外部合约上的未知的函数。这种行为是非常有必要的,因为 [Call Depth Attack][7] 直到 [EIP-150][3] 才被启用。在硬分叉之后,这个重入bug 将不再可能出现了,并且提取模式不提供任何比直接通证调用更好的安全性了。
|
||||
|
||||
但是,为什么现在它成了一个问题呢?可能是由于某些原因,它的用法设计有些欠佳,但是我们可以通过前端的 DApp 来修复这个问题,对吗?
|
||||
|
||||
因此,我们来看一看,如果一个用户使用 `transfer` 去转账一些通证到智能合约会发生什么事情。Alice 在带合约地址的通证合约上调用 `transfer`
|
||||
|
||||
**….aaaaand 它不见了!**
|
||||
|
||||
是的,通证没有了。很有可能,没有任何人再能拿回通证了。但是像 Alice 的这种做法并不鲜见,正如 ERC-223 的发明者 Dexaran 所发现的,大约有 $400.000 的通证(由于 ETH 波动很大,我们只能说很多)是由于用户意外发送到智能合约中,并因此而丢失。
|
||||
|
||||
即便合约开发者是一个非常友好和无私的用户,他也不能创建一个合约以便将它收到的通证返还给你。因为合约并不会提示这类转账,并且事件仅在通证合约上发出。
|
||||
|
||||
从软件工程师的角度来看,那就是 ERC-20 的重大缺点。如果发生一个事件(为简单起见,我们现在假设以太坊交易是真实事件),对参与的当事人将有一个提示。但是,这个事件是在通证智能合约中触发的,合约接收方是无法知道它的。
|
||||
|
||||
目前,还不能做到防止用户向智能合约发送通证,并且在 ERC-20 通证合约上使用不直观转账将导致这些发送的通证永远丢失。
|
||||
|
||||
### 帝国反击战:ERC-223
|
||||
|
||||
[Dexaran][8] 第一个提出尝试去修复 ERC-20 的问题。这个提议通过将 EOA 和智能合约账户做不同的处理的方式来解决这个问题。
|
||||
|
||||
强制的策略是去反转调用链(并且使用 [EIP-150][3] 解决它现在能做到了),并且在正接收的智能合约上使用一个预定义的回调(tokenFallback)。如果回调没有实现,转账将失败(将消耗掉发送方的汽油,这是 ERC-223 被批的最常见的一个地方)。
|
||||
|
||||
![][9]
|
||||
|
||||
#### 好处:
|
||||
|
||||
* 创建一个新接口,有意不遵守 ERC-20 关于弃权的功能
|
||||
|
||||
* 允许合约开发者去处理收到的通证(即:接受/拒绝)并因此遵守事件模式
|
||||
|
||||
* 用一个交易来代替两个交易(transfer vs. approve/transferFrom)并且节省了汽油和区域链的存储空间
|
||||
|
||||
|
||||
|
||||
|
||||
#### 坏处:
|
||||
|
||||
* 如果 `tokenFallback` 不存在,那么合约的 `fallback` 功能将运行,这可能会产生意料之外的副作用
|
||||
|
||||
* 如果合约假设使用通证转账,比如,发送通证到一个特定的像多签名钱包一样的账户,这将使 ERC-223 通证失败,它将不能转移(即它们会丢失)。
|
||||
|
||||
|
||||
### 程序员修练之道:ERC-677
|
||||
|
||||
[ERC-667 transferAndCall 通证标准][10] 尝试将 ERC-20 和 ERC-223 结合起来。这个创意是在 ERC-20 中引入一个 `transferAndCall` 函数,并保持标准不变。ERC-223 有意不完全向后兼容,由于不再需要 approve/allowance 模式,并因此将它删除。
|
||||
|
||||
ERC-667 的主要目标是向后兼容,为新合约向外部合约转账提供一个安全的方法。
|
||||
|
||||
![][11]
|
||||
|
||||
#### 好处:
|
||||
|
||||
* 容易适用新的通证
|
||||
|
||||
* 兼容 ERC-20
|
||||
|
||||
* 为 ERC-20 设计的适配器用于安全使用 ERC-20
|
||||
|
||||
#### 坏处:
|
||||
|
||||
* 不是真正的新方法。只是一个 ERC-20 和 ERC-223 的折衷
|
||||
|
||||
* 目前实现 [尚未完成][12]
|
||||
|
||||
|
||||
### 重逢:ERC-777
|
||||
|
||||
[ERC-777 一个新的先进的通证标准][13],引入它是为了建立一个演进的通证标准,它是吸取了像带值的 `approve()` 以及上面提到的将通证发送到合约这样的错误观念的教训之后得来的演进后标准。
|
||||
|
||||
另外,ERC-777 使用了新标准 [ERC-820:使用一个注册合约的伪内省][14],它允许为合约注册元数据以提供一个简单的内省类型。并考虑到了向后兼容和其它的功能扩展,这些取决于由一个 EIP-820 查找到的地址返回的 `ITokenRecipient`,和由目标合约实现的函数。
|
||||
|
||||
ERC-777 增加了许多使用 ERC-20 通证的经验,比如,白名单操作者、提供带 send(…) 的以太兼容的接口,为了向后兼容而使用 ERC-820 去覆盖和调整功能。
|
||||
|
||||
![][15]
|
||||
|
||||
#### 好处:
|
||||
|
||||
* 从 ERC-20 的使用经验上得来的、经过深思熟虑的、进化的通证接口
|
||||
|
||||
* 为内省要求 ERC-820 使用新标准,接受了增加的功能
|
||||
|
||||
* 白名单操作者非常有用,而且比 approve/allowance 更有必要,它经常是无限的
|
||||
|
||||
|
||||
#### 坏处:
|
||||
|
||||
* 刚刚才开始,复杂的依赖合约调用的结构
|
||||
|
||||
* 依赖导致出现安全问题的可能性增加:第一个安全问题并不是在 ERC-777 中 [确认(并解决的)][16],而是在最新的 ERC-820 中
|
||||
|
||||
|
||||
|
||||
|
||||
### (纯主观的)结论(轻喷)
|
||||
|
||||
目前为止,如果你想遵循 “行业标准”,你只能选择 ERC-20。它获得了最广泛的理解与支持。但是,它还是有缺陷的,最大的一个缺陷是因为非专业用户设计和规范问题导致的用户真实地损失金钱的问题。ERC-223 是非常好的,并且在理论上找到了 ERC-20 中这个问题的答案了,它应该被考虑为 ERC-20 的一个很好的替代标准。在一个新通证中实现这两个接口并不复杂,并且可以降低汽油的使用。
|
||||
|
||||
ERC-677 是事件和金钱丢失问题的一个务实的解决方案,但是它并没能提供足够多的新方法,以促使它成为一个标准。但是它可能是 ERC-20 2.0 的一个很好的候选者。
|
||||
|
||||
ERC-777 是一个更先进的通证标准,它应该成为 ERC-20 的合法继任者,它提供了以太坊平台所需要的非常好的成熟概念,像白名单操作者,并允许以优雅的方式进行扩展。由于它的复杂性和对其它新标准的依赖,在主链上出现第一个 ERC-777 标准的通证还需要些时日。
|
||||
|
||||
### 链接
|
||||
|
||||
[1] 在 ERC-20 中使用 approve/transferFrom-Pattern 的安全问题: <https://drive.google.com/file/d/0ByMtMw2hul0EN3NCaVFHSFdxRzA/view>
|
||||
|
||||
[2] ERC-20 中的无事件操作:<https://docs.google.com/document/d/1Feh5sP6oQL1-1NHi-X1dbgT3ch2WdhbXRevDN681Jv4>
|
||||
|
||||
[3] ERC-20 的故障及历史:<https://github.com/ethereum/EIPs/issues/223#issuecomment-317979258>
|
||||
|
||||
[4] ERC-20/223 的不同之处:<https://ethereum.stackexchange.com/questions/17054/erc20-vs-erc223-list-of-differences>
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: http://blockchainers.org/index.php/2018/02/08/token-erc-comparison-for-fungible-tokens/
|
||||
|
||||
作者:[Alexander Culum][a]
|
||||
选题:[lujun9972](https://github.com/lujun9972)
|
||||
译者:[qhwdw](https://github.com/qhwdw)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:http://blockchainers.org/index.php/author/alex/
|
||||
[1]:https://www.goodreads.com/quotes/589703-the-good-thing-about-standards-is-that-there-are-so
|
||||
[2]:https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md
|
||||
[3]:https://github.com/ethereum/EIPs/blob/master/EIPS/eip-150.md
|
||||
[4]:https://medium.com/@jgm.orinoco/understanding-erc-20-token-contracts-a809a7310aa5
|
||||
[5]:http://blockchainers.org/wp-content/uploads/2018/02/ERC-20-Token-Transfer-2.png
|
||||
[6]:http://matthewtmead.com/blog/hollywood-principle-dont-call-us-well-call-you-4/
|
||||
[7]:https://consensys.github.io/smart-contract-best-practices/known_attacks/
|
||||
[8]:https://github.com/Dexaran
|
||||
[9]:http://blockchainers.org/wp-content/uploads/2018/02/ERC-223-Token-Transfer-1.png
|
||||
[10]:https://github.com/ethereum/EIPs/issues/677
|
||||
[11]:http://blockchainers.org/wp-content/uploads/2018/02/ERC-677-Token-Transfer.png
|
||||
[12]:https://github.com/ethereum/EIPs/issues/677#issuecomment-353871138
|
||||
[13]:https://github.com/ethereum/EIPs/issues/777
|
||||
[14]:https://github.com/ethereum/EIPs/issues/820
|
||||
[15]:http://blockchainers.org/wp-content/uploads/2018/02/ERC-777-Token-Transfer.png
|
||||
[16]:https://github.com/ethereum/EIPs/issues/820#issuecomment-362049573
|
@ -1,28 +1,27 @@
|
||||
Translating by qhwdw
|
||||
Passwordless Auth: Client
|
||||
无密码验证:客户端
|
||||
======
|
||||
Time to continue with the [passwordless auth][1] posts. Previously, we wrote an HTTP service in Go that provided with a passwordless authentication API. Now, we are gonna code a JavaScript client for it.
|
||||
我们继续 [无密码验证][1] 的文章。上一篇文章中,我们用 Go 写了一个 HTTP 服务,用这个服务来做无密码验证 API。今天,我们为它再写一个 JavaScript 客户端。
|
||||
|
||||
We’ll go with a single page application (SPA) using the technique I showed [here][2]. Read it first if you haven’t yet.
|
||||
我们将使用 [这里的][2] 这个单页面应用程序(SPA)来展示使用的技术。如果你还没有读过它,请先读它。
|
||||
|
||||
For the root URL (`/`) we’ll show two different pages depending on the auth state: a page with an access form or a page greeting the authenticated user. Another page is for the auth callback redirect.
|
||||
我们将根据验证的状态分别使用两个不同的根 URL(`/`):一个是访问状态的页面或者是欢迎已验证用户的页面。另一个页面是验证失败后重定向到验证页面。
|
||||
|
||||
### Serving
|
||||
|
||||
I’ll serve the client with the same Go server, so let’s add some routes to the previous `main.go`:
|
||||
我们将使用相同的 Go 服务器来为客户端提供服务,因此,在我们前面的 `main.go` 中添加一些路由:
|
||||
```
|
||||
router.Handle("GET", "/js/", http.FileServer(http.Dir("static")))
|
||||
router.HandleFunc("GET", "/...", serveFile("static/index.html"))
|
||||
|
||||
```
|
||||
|
||||
This serves files under `static/js`, and `static/index.html` is served for everything else.
|
||||
这个伺服文件在 `static/js` 下,而 `static/index.html` 文件是为所有的访问提供服务的。
|
||||
|
||||
You can use your own server apart, but you’ll have to enable [CORS][3] on the server.
|
||||
你可以使用你自己的服务器,但是你得在服务器上启用 [CORS][3]。
|
||||
|
||||
### HTML
|
||||
|
||||
Let’s see that `static/index.html`.
|
||||
我们来看一下那个 `static/index.html` 文件。
|
||||
```
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
@ -38,13 +37,13 @@ Let’s see that `static/index.html`.
|
||||
|
||||
```
|
||||
|
||||
Single page application left all the rendering to JavaScript, so we have an empty body and a `main.js` file.
|
||||
单页面应用程序剩余的渲染由 JavaScript 来完成,因此,我们使用了一个空的 body 部分和一个 `main.js` 文件。
|
||||
|
||||
I’ll user the Router from the [last post][2].
|
||||
我们将使用 [上篇文章][2] 中的 Router。
|
||||
|
||||
### Rendering
|
||||
|
||||
Now, create a `static/js/main.js` file with the following content:
|
||||
现在,我们使用下面的内容来创建一个 `static/js/main.js` 文件:
|
||||
```
|
||||
import Router from 'https://unpkg.com/@nicolasparada/router'
|
||||
import { isAuthenticated } from './auth.js'
|
||||
@ -73,11 +72,11 @@ function guard(fn1, fn2 = view('welcome')) {
|
||||
|
||||
```
|
||||
|
||||
Differing from the last post, we implement an `isAuthenticated()` function and a `guard()` function that uses it to render one or another page. So when a user visits `/` it will show the home or welcome page whether the user is authenticated or not.
|
||||
与上篇文章不同的是,我们实现了一个 `isAuthenticated()` 函数和一个 `guard()` 函数,使用它去渲染两种验证状态的页面。因此,当用户访问 `/` 时,它将根据用户是否通过了验证来展示 home 页面或者是欢迎页面。
|
||||
|
||||
### Auth
|
||||
|
||||
Now, let’s write that `isAuthenticated()` function. Create a `static/js/auth.js` file with the following content:
|
||||
现在,我们来编写 `isAuthenticated()` 函数。使用下面的内容来创建一个 `static/js/auth.js` 文件:
|
||||
```
|
||||
export function getAuthUser() {
|
||||
const authUserItem = localStorage.getItem('auth_user')
|
||||
@ -102,18 +101,18 @@ export function isAuthenticated() {
|
||||
|
||||
```
|
||||
|
||||
When someone login, we save the JSON web token, expiration date of it and the current authenticated user on `localStorage`. This module uses that.
|
||||
当有人登入时,我们将保存 JSON 格式的 web 令牌、过期日期、以及在 `localStorage` 上的当前已验证用户。这个模块就是这个用处。
|
||||
|
||||
* `getAuthUser()` gets the authenticated user from `localStorage` making sure the JSON Web Token hasn’t expired yet.
|
||||
* `isAuthenticated()` makes use of the previous function to check whether it doesn’t return `null`.
|
||||
* `getAuthUser()` 用于从 `localStorage` 获取已认证的用户,以确认 JSON 格式的 Web 令牌没有过期。
|
||||
* `isAuthenticated()` 在前面的函数中用于去检查它是否返回了 `null`。
|
||||
|
||||
|
||||
|
||||
### Fetch
|
||||
|
||||
Before continuing with the pages, I’ll code some HTTP utilities to work with the server API.
|
||||
在继续这个页面之前,我将写一些与服务器 API 一起使用的 HTTP 工具。
|
||||
|
||||
Let’s create a `static/js/http.js` file with the following content:
|
||||
我们使用以下的内容去创建一个 `static/js/http.js` 文件:
|
||||
```
|
||||
import { isAuthenticated } from './auth.js'
|
||||
|
||||
@ -160,11 +159,11 @@ export default {
|
||||
|
||||
```
|
||||
|
||||
This module exports `get()` and `post()` functions. They are wrappers around the `fetch` API. Both functions inject an `Authorization: Bearer <token_here>` header to the request when the user is authenticated; that way the server can authenticate us.
|
||||
这个模块导出了 `get()` 和 `post()` 函数。它们是 `fetch` API 的封装。当用户是已验证的,这二个函数注入一个 `Authorization: Bearer <token_here>` 头到请求中;这样服务器就能对我们进行身份验证。
|
||||
|
||||
### Welcome Page
|
||||
|
||||
Let’s move to the welcome page. Create a `static/js/pages/welcome-page.js` file with the following content:
|
||||
我们现在来到欢迎页面。用如下的内容创建一个 `static/js/pages/welcome-page.js` 文件:
|
||||
```
|
||||
const template = document.createElement('template')
|
||||
template.innerHTML = `
|
||||
@ -187,11 +186,11 @@ export default function welcomePage() {
|
||||
|
||||
```
|
||||
|
||||
This page uses an `HTMLTemplateElement` for the view. It is just a simple form to enter the user’s email.
|
||||
正如你所见,这个页面使用一个 `HTMLTemplateElement`。这是一个只输入用户 email 的简单表格。
|
||||
|
||||
To not make this boring, I’ll skip error handling and just log them to console.
|
||||
为了不让代码太乏味,我将跳过错误处理部分,只是将它们输出到控制台上。
|
||||
|
||||
Now, let’s code that `onAccessFormSubmit()` function.
|
||||
现在,我们来写 `onAccessFormSubmit()` 函数。
|
||||
```
|
||||
import http from '../http.js'
|
||||
|
||||
@ -225,7 +224,7 @@ function wantToCreateAccount() {
|
||||
|
||||
```
|
||||
|
||||
It does a `POST` request to `/api/passwordless/start` with the email and redirectUri in the body. In case it returns with `404 Not Found` status code, we’ll create a user.
|
||||
它使用 email 做了一个 `POST` 请求到 `/api/passwordless/start`,然后在 body 中做了 URI 转向。在本例中使用 `404 Not Found` 状态码返回,我们将创建一个用户。
|
||||
```
|
||||
function runCreateUserProgram(email) {
|
||||
const username = prompt("Enter username")
|
||||
@ -239,11 +238,11 @@ function runCreateUserProgram(email) {
|
||||
|
||||
```
|
||||
|
||||
The user creation program, first, ask for username and does a `POST` request to `/api/users` with the email and username in the body. On success, it sends a magic link for the user created.
|
||||
这个用户创建程序,首先询问用户名,然后使用 email 和用户名,在 body 中做一个 `POST` 请求到 `/api/users`。成功之后,给创建的用户发送一个魔法链接。
|
||||
|
||||
### Callback Page
|
||||
|
||||
That was all the functionality for the access form, let’s move to the callback page. Create a `static/js/pages/callback-page.js` file with the following content:
|
||||
这就是访问表格的所有功能,现在我们来做回调页面。使用如下的内容来创建一个 `static/js/pages/callback-page.js` 文件:
|
||||
```
|
||||
import http from '../http.js'
|
||||
|
||||
@ -279,13 +278,13 @@ export default function callbackPage() {
|
||||
|
||||
```
|
||||
|
||||
To remember… when clicking the magic link, we go to `/api/passwordless/verify_redirect` which redirect us to the redirect URI we pass (`/callback`) with the JWT and expiration date in the URL hash.
|
||||
请记住 … 当点击魔法链接时,我们来到 `/api/passwordless/verify_redirect`,我们通过 (`/callback`)在 URL 的哈希中传递 JWT 和过期日期,将我们转向到重定向 URI。
|
||||
|
||||
The callback page decodes the hash from the URL to extract those parameters to do a `GET` request to `/api/auth_user` with the JWT saving all the data to `localStorage`. Finally, it just redirects to home.
|
||||
回调页面解码 URL 中的哈希,提取这些参数去做一个 `GET` 请求到 `/api/auth_user`,用 JWT 保存所有数据到 `localStorage` 中。最后,重定向到主页面。
|
||||
|
||||
### Home Page
|
||||
|
||||
Create a `static/pages/home-page.js` file with the following content:
|
||||
创建如下内容的 `static/pages/home-page.js` 文件:
|
||||
```
|
||||
import { getAuthUser } from '../auth.js'
|
||||
|
||||
@ -314,9 +313,9 @@ function logout() {
|
||||
|
||||
```
|
||||
|
||||
This page greets the authenticated user and also has a logout button. The `logout()` function just clears `localStorage` and reloads the page.
|
||||
这个页面欢迎已验证用户,同时也有一个登出按钮。`logout()` 函数的功能只是清理掉 `localStorage` 并重载这个页面。
|
||||
|
||||
There is it. I bet you already saw the [demo][4] before. Also, the source code is in the same [repository][5].
|
||||
这就是全部内容了。我敢说你在此之前已经看过这个 [demo][4] 了。当然,这些源代码也在同一个 [仓库][5] 中。
|
||||
|
||||
👋👋👋
|
||||
|
||||
@ -326,7 +325,7 @@ via: https://nicolasparada.netlify.com/posts/passwordless-auth-client/
|
||||
|
||||
作者:[Nicolás Parada][a]
|
||||
选题:[lujun9972](https://github.com/lujun9972)
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
译者:[qhwdw](https://github.com/qhwdw)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
Loading…
Reference in New Issue
Block a user