iT邦幫忙

2022 iThome 鐵人賽

DAY 20
0
Modern Web

使用 Vue 3 從 0 到 1 架設網站!!!系列 第 20

登入的 API 串接,取得 JWT 後,存至 localStorage

  • 分享至 

  • xImage
  •  

今天要來寫登入的 API 串接,取得 JWT 後,存至 localStorage。

將 Key 存在另個檔案

目前先用程式動態產生 key 的方式,之後有機會再來研究產生公私鑰。
動態產生 key 的話,在驗證 jwt 時,如果有將 container 容器重啟的話,那麼原來產生的 jwt 自然就會驗證不通過,因為 key 已經變了。

在 webmix_api 資料夾底下,建立 apiKey.ts 檔案,內容如下:

// 產生 key
export const key = await crypto.subtle.generateKey(
  { name: "HMAC", hash: "SHA-256" },
  true,
  ["sign", "verify"],
);

改寫登入的 API

開啟 resolvers.ts 檔案,最上方加底下這行:

import { key } from "./apiKey.ts";

然後多一個函式如下,取得特定 email 的使用者:

async function getUser(email){
  return await client.query("SELECT * FROM users WHERE email = '" + email + "'");
}

然後原來的 authUser 函式,改寫如下,主要會有 密碼驗證的功能,以及若密碼驗證通過,那就產生 JWT 回傳:

async function authUser(args){

  let user_data = await getUser(args.username);
  //console.log(user_data[0].password);

  if(user_data.length > 0){
    // 解密
    const pwd_result = await bcrypt.compare(args.password, user_data[0].password);
    if(pwd_result){ // 密碼核對通過,回傳 JWT

      // 產生 jwt
      let jwt = await create({ alg: "HS256", typ: "JWT" }, {
        id: user_data[0].id,
        nickname: user_data[0].nickname,
        exp: getNumericDate(60 * 60)}, key
      );

      return jwt;
    }
  }
  return "false";

}

Vue 頁面,登入功能串接 API

在 webmix_efficiency 資料夾下,src/views/Home.vue 檔案,在 script 標籤內,加上以下的程式:

這段程式,主要有幾個用途:

  • data() 函式當中的 email 及 password 一樣後面會在 介面上加 v-model 來做雙向綁定。
  • auth_user() 函式,在使用者點擊登入按鈕時,就會執行此函式。
  • auth_user() 函式的執行,這邊直接執行串接 API。
  • 取得 API 回傳的資料後,檢查是否有 JWT,有的話,那就將 JWT 存至 localStorage,並且頁面重新整理。
<script>
  export default {
    data(){
      return {
        email: "",
        password: ""
      };
    },
    methods: {
      auth_user(){
        fetch("http://localhost:8080/graphql", {
          method: 'POST',
          body: JSON.stringify({
            query: `mutation {
              authUser(username: "${this.email}", password: "${this.password}")
            }`
          })
        }).then(res => res.json()).then(data => {
          if(data.data !== null && data.data.authUser !== "false"){
            localStorage.setItem("jwt", data.data.authUser);
            alert("登入成功");
            location.reload();
          }else{
            alert("登入失敗");
          }
        });

      }
    }
  }
</script>

然而在 template 標籤內,以下這行:

input(type="text")

改成:

input(type="text" v-model="email")

以下這行:

input(type="password")

改成:

input(type="password" v-model="password")

以下這行:

button(type="button") 登入

改成:

button(type="button" @click="auth_user") 登入

改完後,就可以實際測試看看囉,在登入頁面,輸入帳、密,按下登入按鈕,成功的話,就會跳成功的 alert,然後頁面會重新整理,就可以看看 localStorage 是否有 JWT 喔,如下圖藍框處:

https://ithelp.ithome.com.tw/upload/images/20220920/20069901Bv3zPo8jYT.png

太好了,有存下來了。

結語

存下 JWT 之後,後續就可以檢查目前使用者的登入狀態囉。倒數十天了!


上一篇
Vue 串接 GraphQL API(註冊會員) - 使用 fetch 語法
下一篇
Vue 頁面的登入狀態及登出
系列文
使用 Vue 3 從 0 到 1 架設網站!!!30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言