溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

dashboard創(chuàng)建密鑰時前端的數(shù)據(jù)怎么傳到后端

發(fā)布時間:2021-12-20 16:42:06 來源:億速云 閱讀:141 作者:iii 欄目:互聯(lián)網(wǎng)科技

這篇文章主要介紹“dashboard創(chuàng)建密鑰時前端的數(shù)據(jù)怎么傳到后端”,在日常操作中,相信很多人在dashboard創(chuàng)建密鑰時前端的數(shù)據(jù)怎么傳到后端問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”dashboard創(chuàng)建密鑰時前端的數(shù)據(jù)怎么傳到后端”的疑惑有所幫助!接下來,請跟著小編一起來學(xué)習(xí)吧!

我們創(chuàng)建一個密鑰和相應(yīng)的帳戶,就是下面這張圖所對應(yīng)的: dashboard創(chuàng)建密鑰時前端的數(shù)據(jù)怎么傳到后端 

當(dāng)我們點擊了"Register"按鈕以后,我們在前端頁面上填寫的參數(shù),到底是如何一步步的傳到比原的后端的。

跟之前一樣,我們將對這個問題進行細分,然后各個擊破:

  1. 前端:當(dāng)我們填完表單,點了提交以后,比原在前端是如何發(fā)送數(shù)據(jù)的?

  2. 后端:比原的后端是如何接收到數(shù)據(jù)的?

前端:當(dāng)我們填完表單,點了提交以后,數(shù)據(jù)會發(fā)送到后端的哪個接口?

當(dāng)我們點擊了"Register"按鈕,在前端頁面中,一定會在某個地方觸發(fā)一個向比原節(jié)點webapi接口發(fā)出請求的操作。究竟是訪問的哪個web api?提交的數(shù)據(jù)又是什么樣的呢?讓我們先從前端代碼中尋找一下。

注意,比原的前端代碼位于另一個項目倉庫bytom/dashboard中。為了能與我們在本系列文章中使用的比原v1.0.1的代碼相匹配,我找到了dashboard中的v1.0.0的代碼,并且提交到了一個單獨的項目中:freewind/bytom-dashboard-v1.0.0。注意該項目代碼未做任何修改,其master分支對應(yīng)于官方代碼倉庫的v1.0.0分支。之所以要弄一個單獨的出來,這是因為我們在文章中,每次引用一段代碼的時候,都會給出相應(yīng)的github上的鏈接,方便讀者跳過去查看全貌,使用一個獨立項目,會讓這個過程更簡便一些。

由于比原的前端頁面是使用React為主的,所以我猜想在代碼中,也該會有一個名為Register的組件,或者某個表單中有一個名為Register的按鈕。經(jīng)過搜索,我們幸運的發(fā)現(xiàn)了Register.jsx 這個組件文件,它正好是我們需要的。

經(jīng)過高度簡化后的代碼如下:

src/features/app/components/Register/Register.jsx#L9-L148

class Register extends React.Component {
  // ...
  // 4. 
  submitWithErrors(data) {
    return new Promise((resolve, reject) => {
      // 5. 
      this.props.registerKey(data)
        .catch((err) => reject({_error: err.message}))
    })
  }
  // ...

  render() {
    // ...
    return (
      // ...
      // 3.
      <form className={styles.form} onSubmit={handleSubmit(this.submitWithErrors)}>
        // 1.
        <TextField
          title={lang === 'zh' ? '賬戶別名' : 'Account Alias'}
          placeholder={lang === 'zh' ? '請輸入賬戶別名...' : 'Please enter the account alias...'}
          fieldProps={accountAlias} />
        <TextField
          title={lang === 'zh' ? '密鑰別名' : 'Key Alias'}
          placeholder={lang === 'zh' ? '請輸入密鑰別名...' : 'Please enter the key alias...'}
          fieldProps={keyAlias}/>
        <TextField
          title={lang === 'zh' ? '密鑰密碼' : 'Key Password'}
          placeholder={lang === 'zh' ? '請輸入密鑰密碼...' : 'Please enter the key password...'}
          fieldProps={password}
          type='password'/>
        <TextField
          title={lang === 'zh' ? '重復(fù)輸入密鑰密碼' : 'Repeat your key password'}
          placeholder={lang === 'zh' ? '請重復(fù)輸入密鑰密碼...' : 'Please repeat the key password...'}
          fieldProps={repeatPassword}
          type='password'/>

        // 2. 
        <button type='submit' className='btn btn-primary' disabled={submitting}>
          {lang === 'zh' ? '注冊' : 'Register'}
        </button>
        // ....
        </form>
      // ...
    )
  }
}

上面的代碼,共有5個地方需要注意,被我用數(shù)字標示出來了。注意這5個數(shù)字并不是從上到下標注,而是按照我們關(guān)注的順序來的:

  1. 表單上的各個輸入框,就是我們填寫別名和密碼的地方。這里需要關(guān)注的是每個TextFieldfieldProps屬性,它對應(yīng)我們提交到后臺的數(shù)據(jù)的name

  2. 就是那個“Register”按鈕了。需要注意的是,它的typesubmit,也就是說,點擊它以后,將會觸發(fā)所在formonSubmit方法

  3. 回到了form的開頭。注意它的onSubmit里面,調(diào)用的是handleSubmit(this.submitWithErrors)。其中的handleSubmit是從該表單所使用的第三方redux-form中傳入的,用來處理表單提交,我們在這里不關(guān)注它,只需要知道我們需要把自己的處理函數(shù)this.submitWithErrors傳給它。而在后者中,我們將會調(diào)用比原節(jié)點提供的web api

  4. 第3步中的this.submitWithErrors最終將走到這里定義的submitWithErrors函數(shù)

  5. submitWithErrors將會發(fā)起一個異步請求,最終調(diào)用由外部傳進來的registerKey函數(shù)

從這里我們還看不到調(diào)用的是哪個api,所以我們必須繼續(xù)去尋找registerKey。很快就在同文件中找到了registerKey

src/features/app/components/Register/Register.jsx#L176-L180

(dispatch) => ({
    registerKey: (token) => dispatch(actions.core.registerKey(token)),
    // ...
  })

它又將會調(diào)用actions.core.registerKey這個函數(shù):

src/features/core/actions.js#L44-L87

const registerKey = (data) => {
  return (dispatch) => {
    // ...
    // 1.1
    const keyData = {
      'alias': data.keyAlias,
      'password': data.password
    }
    // 1.2
    return chainClient().mockHsm.keys.create(keyData)
      .then((resp) => {
        // ...
        // 2.1
        const accountData = {
          'root_xpubs':[resp.data.xpub],
          'quorum':1,
          'alias': data.accountAlias}
        // 2.2
        dispatch({type: 'CREATE_REGISTER_KEY', data})

        // 2.3
        chainClient().accounts.create(accountData)
          .then((resp) => {
            // ...
            // 2.4
            if(resp.status === 'success') {
              dispatch({type: 'CREATE_REGISTER_ACCOUNT', resp})
            }
          })
    // ...
      })
    // ...
  }
}

可以看到,在這個函數(shù)中,做的事情還是很多的。而且并不是我一開始預(yù)料的調(diào)用一次后臺接口就行了,而是調(diào)用了兩次(分別是創(chuàng)建密鑰和創(chuàng)建帳戶)。下面進行分析:

  1. 1.1是為了讓后臺創(chuàng)建密鑰而需要準備的參數(shù),一個是alias,一個是password,它們都是用戶填寫的

  2. 1.2是調(diào)用后臺用于創(chuàng)建密鑰的接口,把keyData傳過去,并且拿到返回的resp后,進行后續(xù)的處理

  3. 2.1是為了讓后臺創(chuàng)建帳戶而需要準備的參數(shù),分別是root_xpubs, quorumalias,其中root_xpubs是創(chuàng)建密鑰后返回的公鑰,quorum目前不知道(TODO),alias是用戶填寫的帳戶別名

  4. 2.2這一句沒有作用(經(jīng)過官方確認了),因為我在代碼中沒有找到處理CREATE_REGISTER_KEY的代碼。可以看這個issue#28

  5. 2.3調(diào)用后臺創(chuàng)建帳戶,把accountData傳過去,可以拿到返回的resp

  6. 2.4調(diào)用成功后,再使用redux的dispatch函數(shù)分發(fā)一個CREATE_REGISTER_ACCOUNT信息。不過這個信息好像也沒有太大用處。

關(guān)于CREATE_REGISTER_ACCOUNT,我在代碼中找到了兩處相關(guān):

  1. src/features/core/reducers.js#L229-L234

const accountInit = (state = false, action) => {
  if (action.type == 'CREATE_REGISTER_ACCOUNT') {
    return true
  }
  return state
}
  1. src/features/app/reducers.js#L10-L115

export const flashMessages = (state = {}, action) => {
  switch (action.type) {
    // ...
    case 'CREATE_REGISTER_ACCOUNT': {
      return newSuccess(state, 'CREATE_REGISTER_ACCOUNT')
    }
    // ...
  }
}

第一個看起來沒什么用,第二個應(yīng)該是用來在操作完成后,顯示相關(guān)的錯誤信息。

那就讓我們把關(guān)注點放在1.22.3這兩個后臺調(diào)用的地方吧。

  1. chainClient().mockHsm.keys.create(keyData)對應(yīng)的是:

src/sdk/api/mockHsmKeys.js#L3-L31

const mockHsmKeysAPI = (client) => {
  return {
    create: (params, cb) => {
      let body = Object.assign({}, params)
      const uri = body.xprv ? '/import-private-key' : '/create-key'

      return shared.tryCallback(
        client.request(uri, body).then(data => data),
        cb
      )
    },
    // ...
  }
}

可以看到在create方法中,如果找不到body.xprv(就是本文對應(yīng)的情況),則會調(diào)用后臺的/create-key接口。經(jīng)過一長串的跟蹤,我們終于找到了一個。

  1. chainClient().accounts.create(accountData)對應(yīng)的是:

src/sdk/api/accounts.js#L3-L30

const accountsAPI = (client) => {
  return {
    create: (params, cb) => shared.create(client, '/create-account', params, {cb, skipArray: true}),
    // ...
  }
}

很快我們在這邊,也找到了創(chuàng)建帳戶時調(diào)用的接口為/create-account

前端這邊,我們終于分析完了。下一步,將進入比原的節(jié)點(也就是后端)。

后端:比原的后端是如何接收到數(shù)據(jù)的?

如果我們對前一篇文章還有印象的話,會記得比原在啟動之后,會在Node.initAndstartApiServer方法中啟動web api對應(yīng)的http服務(wù),并且在API.buildHandler()方法中會配置很多的功能點,其中一定會有我們這里調(diào)用的接口。

讓我們看看API.buildHandler方法:

api/api.go#L164-L244

func (a *API) buildHandler() {
    walletEnable := false
    m := http.NewServeMux()

    if a.wallet != nil {
        walletEnable = true
        // ...
        m.Handle("/create-account", jsonHandler(a.createAccount))
        // ...
        m.Handle("/create-key", jsonHandler(a.pseudohsmCreateKey))
        // ...

很快,我們就發(fā)現(xiàn)了:

  1. /create-account: 對應(yīng)a.createAccount

  2. /create-key: 對應(yīng)a.pseudohsmCreateKey

讓我們先看一下a.pseudohsmCreateKey

api/hsm.go#L23-L32

func (a *API) pseudohsmCreateKey(ctx context.Context, in struct {
    Alias    string `json:"alias"`
    Password string `json:"password"`
}) Response {
    // ...
}

可以看到,pseudohsmCreateKey的第二個參數(shù),是一個struct,它有兩個字段,分別是AliasPassword,這正好和前面從前端傳過來的參數(shù)keyData對應(yīng)。那么這個參數(shù)的值是怎么由提交的JSON數(shù)據(jù)轉(zhuǎn)換過來的呢?上次我們說到,主要是由a.pseudohsmCreateKey外面套著的那個jsonHandler進行的,它會處理與http協(xié)議相關(guān)的操作,以及把JSON數(shù)據(jù)轉(zhuǎn)換成這里需要的Go類型的參數(shù),pseudohsmCreateKey就可以直接用了。

由于在這個小問題中,我們問題的邊界是比原后臺是如何拿到數(shù)據(jù)的,所以我們到這里就可以停止對這個方法的分析了。它具體是怎么創(chuàng)建密鑰的,這在以后的文章中將詳細討論。

再看a.createAccount

api/accounts.go#L15-L30

// POST /create-account
func (a *API) createAccount(ctx context.Context, ins struct {
    RootXPubs []chainkd.XPub `json:"root_xpubs"`
    Quorum    int            `json:"quorum"`
    Alias     string         `json:"alias"`
}) Response {
    // ...
}

與前面一樣,這個方法的參數(shù)RootXPubs、QuorumAlias也是由前端提交,并且由jsonHandler自動轉(zhuǎn)換好的。

到此,關(guān)于“dashboard創(chuàng)建密鑰時前端的數(shù)據(jù)怎么傳到后端”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識,請繼續(xù)關(guān)注億速云網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>

向AI問一下細節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI