Hi 游客

更多精彩,请登录!

比特池塘 区块链技术 正文
    今天去中心化身份逐渐被广泛采用。用户的部分在线活动在链上是公开的,可通过加密钱包搜索到,用户在链上创造、贡献、赚取和拥有的东西,都反映了他们的喜好,也逐渐积累成该用户的身份和标识。7 R8 d  I2 ^6 @, b5 ?2 P

6 q) P! l: [0 z, I( _    当我们的用户厌倦了传统的电子邮件/密码注册流程时,他们会选择Google、GitHub等社交登录方式,这种方式虽然节约了用户的时间,但登录信息也会被第三方平台记录,也就是说我们用平台账号做了什么,平台都会一目了然,甚至还会对我们的行为进行分析、画像。那么有没有一种登录方式,它的所有信息都只保存在客户端和后端,并不牵扯三方平台授权,最大化的保证用户隐私呢?Web3.0给我们提供了一种选择:MetaMask。
. n) j4 Z" m! P$ T' [* h+ ]+ O7 u! O0 N% A7 R/ f
    MetaMask# Y& Z0 h! C# n5 u3 e
    MetaMask是用于与以太坊区块链进行交互的软件加密货币钱包。MetaMask允许用户通过浏览器插件或移动应用程序访问其以太坊钱包,然后可以使用这些扩展程序与去中心化应用程序进行交互。当然了,首先需要拥有一个MetaMask钱包,进入https://chrome.google.com/websto ... oehlefnkodbefgpgknn
" b1 r# b/ _0 Z0 e1 s6 G
7 I! V% d% v/ Y& R3 l    安装metamask浏览器插件:
. n4 ^( c5 @: f9 F9 |5 X- ?  O6 r

# F9 J8 H, `. j1 X- O# @* U" w0 Z  随后点开插件,创建账号,记录密码、钱包地址、以及助记词等信息。* r; u' o7 ]3 `9 H: _) A

; O! f/ l3 k% o& N! Z& s0 p    安装好插件之后,我们就可以利用这个插件和网站应用做交互了。; Z1 x0 g; ~3 O- g" o5 P+ X

, j1 x+ T$ W( R) d3 N( {2 I    钱包登录流程  y/ w8 h& D: r5 w) U
    登录逻辑和传统的三方登录还是有差异的,传统三方登录一般是首先跳转三方平台进行授权操作,随后三方平台将code验证码返回给登录平台,登录平台再使用code请求三方平台换取token,再通过token请求用户账号信息,而钱包登录则是先在前端通过Web3.js浏览器插件中保存的私钥对钱包地址进行签名操作,随后将签名和钱包地址发送到后端,后端利用Web3的库用同样的算法进行验签操作,如果验签通过,则将钱包信息存入token,并且返回给前端。
( F# r+ Z0 t: j6 N% @: M2 |4 o% }: z$ t$ C  g& k9 u
3 b- A$ Y% B$ A

- p8 U  K2 |& x) Z- B前端签名操作2 _8 U2 u* ~4 j5 [) s
    首先需要下载前端的Web3.0操作库,https://docs.ethers.io/v4/,随后集成到登录页面中:* X2 D) I$ y' A2 H
* ~2 |5 I( S2 b4 n+ ]4 r: t
. T1 f# a: @/ b8 W- ?* t& _
  1. <script src="{{ static_url("js/ethers-v4.min.js") }}"></script>- y6 C& _. g# R. A& D" t+ ?+ K
  2. <script src="{{ static_url("js/axios.js") }}"></script>& z3 F7 l" Z# q( }+ ?8 D* D
  3. <script src="{{ static_url("js/vue.js") }}"></script>
复制代码

5 p4 S+ K. _* N6 d$ J4 y/ B/ y) z* Q6 C7 v) I" |% f! ^2 s4 A

) ~, m7 P1 L$ I& M* }8 w) f' B这里我们基于Vue.js配合Axios使用。0 j; p: I/ _$ q, J

% p! @7 W' z7 S# z3 M* `    接着声明登录激活方法:
6 I. d8 G" l- U$ g+ A( R
# {8 J, }, d1 }9 y5 m4 g
  1. sign_w3:function(){
    6 N7 a# D$ ?+ c' [: L& K
  2. + Q8 L" `! L5 S+ _' V3 d( l
  3.                     that = this;
    9 T4 D( ~; W! u2 u, E/ @9 o1 L
  4.                     ethereum.enable().then(function () {
    / x9 v6 g7 t2 [: s! o) d6 ]

  5. ) R* I" \/ S% o& c3 O  N
  6.     this.provider = new ethers.providers.Web3Provider(web3.currentProvider);6 Z2 E9 T3 I6 c8 s7 {" D! C& f

  7. 6 I* X' ^4 C. f6 K3 L
  8.     this.provider.getNetwork().then(function (result) {* X1 P! U$ m: r, }4 A
  9.         if (result['chainId'] != 1) {
    5 K$ M. \! ], @3 ^

  10. / s: v1 Q( y8 D2 n3 E. S
  11.             console.log("Switch to Mainnet!")+ C& r3 d" w' v4 H8 p

  12. ( e! R" j# q, Q# M/ {! @. @! ~
  13.         } else { // okay, confirmed we're on mainnet
    # O3 g5 k/ n& l3 X9 m8 t
  14. % Y$ w6 b' Z& ~3 B) M1 g: f+ i. }2 |
  15.             this.provider.listAccounts().then(function (result) {
    - E. K& m& V& H' Q
  16.                 console.log(result);: i; d/ `* I: B+ P
  17.                 this.accountAddress = result[0]; // figure out the user's Eth address& t$ u( _( W- R" g, |" H
  18.                 this.provider.getBalance(String(result[0])).then(function (balance) {
    / K% p9 \/ N$ q# ]0 D0 ?1 c4 h
  19.                     var myBalance = (balance / ethers.constants.WeiPerEther).toFixed(4);
    ! ^* M8 i; n5 t2 I
  20.                     console.log("Your Balance: " + myBalance);
    * _- p7 Y- q! _/ o
  21.                 });
    1 ~  q# @( {! Z; E
  22. % m3 f7 [2 S' X! T7 K0 r. e
  23.                 // get a signer object so we can do things that need signing
    , C" V6 x& u  {# F+ b- Q# o  g2 W
  24.                 this.signer = provider.getSigner();
    . N1 ^% b( A6 I) k% N) Z

  25. . z& |" W2 \- A- p, J& `
  26.                 var rightnow = (Date.now()/1000).toFixed(0)' F, b" k$ e. E
  27.         var sortanow = rightnow-(rightnow%600)5 D. ], M9 i/ _0 K2 ?7 i( x

  28. # `- ~8 j, i  M& D* g
  29.         this.signer.signMessage("Signing in to "+document.domain+" at "+sortanow, accountAddress, "test password!")
    0 V# X+ N3 G4 G/ z8 Z2 \
  30.             .then((signature) => {               that.handleAuth(accountAddress,signature);
    ' n  z; U7 X- e: t1 k
  31.             });; R( Z3 t" k+ P  @& Q. x
  32. & A% E/ \/ w" s" M: H( G  @7 g$ O
  33.                 console.log(this.signer);! Z5 X7 m5 Y" Z9 B
  34.             })5 q! R3 n; \5 F$ h' q- A
  35.         }1 P5 G4 C6 o: @
  36.     })- M: g! L2 r. o# J- n
  37. })2 Q* W8 R* G4 a- k9 d$ T: v2 {: C

  38. ) h' d% X8 T( g+ Q2 J$ U0 Z
  39.                 },
复制代码
通过使用signMessage方法返回签名,这里加签过程中使用基于时间戳的随机数防止未签名,当前端签名生成好之后,立刻异步请求后台接口:
$ h! {6 k7 @" d% v4 \6 a& h5 B% s. q6 z1 v1 B- Y
  1. //检查验证7 g4 q1 t- T8 a* p$ e
  2.                 handleAuth:function(accountAddress, signature){
    1 E. ]2 I' Z. U4 m# M! n5 j
  3. 5 G* {8 S! I1 y% d+ `

  4. 7 Y+ w$ k6 R$ X7 Q$ M' o
  5.                     this.myaxios("/checkw3/","post",{"public_address":accountAddress,"signature":signature}).then(data =>{
    ' h4 ~& l, S. a- l0 m2 Z8 y

  6. % K: v( E5 c% g5 v
  7.                         if(data.errcode==0){# E/ d$ Y4 P( u! j. w
  8.                             alert("欢迎:"+data.public_address);! {. ?9 ~3 L1 t$ i8 w" P
  9.                             localStorage.setItem("token",data.token);
    5 o5 m% T6 ?- @: ]% J3 f
  10.                             localStorage.setItem("email",data.public_address);4 x, |, d! b, Z% k! b7 z" x# E
  11.                             window.location.href = "/";
    . e& Y7 k) f% r6 }6 D" e  g% d
  12.                         }else{+ l; Z- |* |' k, O
  13.                             alert("验证失败");' l( s3 N4 D6 |* B6 J
  14.                         }
    ! x8 V$ b: l  G9 r6 |" K
  15.                  });$ {- x/ k$ s1 H3 b1 Y

  16. 4 |- w* f& Z: l" U  ?
  17.   i) ]8 s3 J1 s, z" G

  18. * G. p8 O8 I  U" V& B% {
  19.                 }
复制代码
这里将当前账户的钱包地址和签名传递给后端,如图所示:% F, s. m# m5 u: ?7 Z

2 W8 V' ]/ H9 w' E3 O2 x
7 u$ |" X8 e) g; B5 \" h- K* Y3 @9 D9 `3 b: N! D
# ?/ z/ Z# d" P4 e
随后创建异步视图方法:! n$ `6 u4 Z& J; {* ?. ^% W2 _7 M
  1. from tornado.web import url
    . h+ {5 l/ \4 t2 f. Z
  2. import tornado.web" Z" r! J# c2 [& l& h/ v
  3. from tornado import httpclient% `4 ?  F: M4 N* c& s& C# s
  4. from .base import BaseHandler8 f2 H8 Q, D+ I+ X5 ~; i8 O4 N
  5. from web3.auto import w3
    ( Q0 [/ q% a4 q7 A4 U' L$ d
  6. from eth_account.messages import defunct_hash_message8 }1 h6 E; g. t% ^$ n
  7. import time& W+ ?9 d. n# [0 l6 t7 @# d# Z! Y
  8. 6 P' m/ N( x% P( c+ I3 ~; y
  9. class CheckW3(BaseHandler):# \' ~. h9 S" W' {' Z7 u

  10. 5 |' A' P3 `  H5 i( W# S  s
  11.     async def post(self):
    " J9 }' Q3 W& J! y) m, H

  12. $ a/ V+ x4 p8 a0 r, o. J; F
  13.         public_address = self.get_argument("public_address")3 S, \, H* O4 f
  14.         signature = self.get_argument("signature")
    + o) T/ c! ^) F( v' D
  15. . ]) \( O. k( _5 B  f! d( o
  16.         domain = self.request.host* {' i! ?7 I, E
  17.         if ":" in domain:
    & x; A# g( A* z. B
  18.             domain = domain[0:domain.index(":")]
    / `  k3 f" e' C5 R. q
  19. ( f3 V0 t# E( l; s# z2 u! ^  U
  20.         now = int(time.time())/ ~8 q$ r! Q: ~1 s: D1 H
  21.         sortanow = now-now%600
    - W3 w/ ?0 {! ]% F! _
  22.    8 m) y( x, _. U
  23.         original_message = 'Signing in to {} at {}'.format(domain,sortanow)9 z" j# V8 \% P+ }$ ^  k
  24.         print("[+] checking: "+original_message)! t6 o/ F1 I* H  ~) h) C# C0 c
  25.         message_hash = defunct_hash_message(text=original_message)
    4 X4 W' P2 H4 b8 y& \! l- L
  26.         signer = w3.eth.account.recoverHash(message_hash, signature=signature)
    9 N1 r% [/ T* @, D6 s" N

  27. 8 H9 ~. O+ S4 M6 t% w2 D  G% C5 B
  28.         if signer == public_address:- c/ N, h0 C8 F$ A# V
  29.             try:
    : a  s( [8 |# i3 \
  30.                 user = await self.application.objects.get(User,email=public_address)
    6 ?/ w; u, {5 Y* x1 Y. w" I0 W
  31.             except Exception as e:
    ( Q* R% l5 E6 O
  32.                 user = await self.application.objects.create(User,email=public_address,password=create_password("third"),role=1)6 S8 j+ x8 t1 l4 G" M, z7 e% Y0 w

  33. 8 j. z3 u- t4 q: N  m- T/ \
  34.             myjwt = MyJwt()% W3 f7 o+ K0 j
  35.             token = myjwt.encode({"id":user.id})
    6 x# B3 X$ t/ M0 Q4 g. d
  36.             self.finish({"msg":"ok","errcode":0,"public_address":public_address,"token":token})
    " b6 l, g9 w- i
  37.         else:: k! u$ j$ s1 |7 M& S; Q$ W  t
  38.             self.finish({"msg":"could not authenticate signature","errcode":1})
复制代码

) a$ l& \7 q2 z/ F   这里通过recoverHash方法对签名进行反编译操作,如果反编译后的钱包地址和前端传过来的钱包地址吻合,那么说明当前账户的身份验证通过:. i3 P6 N+ d0 j5 P9 X
, D0 I0 Z/ L! P& W  M! u1 J# q7 S5 |

% e9 a; E5 }1 l0 ^2 X& w- j7 f' V0 r8 m3 D( O3 r4 P

( n) G3 y* n$ O4 l% {, r, k  U 当验签通过之后,利用钱包地址在后台创建账号,随后将钱包地址、token等信息返回给前端,前端将其保存在stroage中即可。
/ G0 M. n( m. m5 F4 d9 F8 m4 ]5 x1 W3 O; ]  ^: _  @
    结语
/ q: R4 w+ o9 E
% B" s9 u: i' h: u* g; R$ A    没错,将至已至,未来已来,是时候将Web3.0区块链技术融入产品了,虽然有些固有的思维方式依然在人们的脑海挥之不去,但世界却在时不我待地变化着,正是:青山遮不住,毕竟东流去!项目开源在https://github.com/zcxey2911/Tornado6_Vuejs3_Edu
9 h  j- ^  i! _# o3 A" S % d! F" O' }- M
# l2 z& S" M- c5 j1 `, ^" x
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

成为第一个吐槽的人

江左没浪 小学生
  • 粉丝

    18

  • 关注

    0

  • 主题

    7