iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 29
1
Modern Web

Think in GraphQL系列 第 29

GraphQL 前端 (3) - Authentication 與 Authorization

header

接著就來做登入/註冊/登出功能吧!但因為這個功能較為複雜,讓我們分為兩天來寫。今天先講個大綱,明天再來實作!

  1. Authentication 方法
  2. Authorization 方法

1. Authentication 方法

在這邊我們使用 token based 的認證方式,所以我們會透過登入從 Server 取得一個 token ,接著我們會將 token 存入瀏覽器的 local storage 裡面。 local storage 裡面有了 token 後,我們要設定在之後的 query 都要帶上 token 讓 Server 可以認證使用者身份,以決定這個 query 是否可以繼續。

為了要實作登入功能,讓我們換一個 server url ,可以使用我寫好的 Apollo LaunchPad 範例 ,或直接帶入新的 url: https://vv49414q93.lp.gql.zone/graphql

首先是登入,我們會在前端新增一個頁面來使用 login mutation 。

img

得到 token 後使用 localStorage.setItem('x-token', data.login.token); 將 token 存在 local storage 內。

接著要如何在每次 request 的 header 都帶上 token 呢 ? 這邊我們要來設定 Apollo Client , 可搭配 官網說明 參考,裡面有一個 request 的設定選項可以讓我們在每次 request 送出時都套用一樣的設定。

const client = new ApolloClient({
  uri: 'https://vv49414q93.lp.gql.zone/graphql',
  request: async operation => {
    const token = await localStorage.getItem('x-token');
    if (token) {
      operation.setContext({
        headers: {
          'x-token': token
        }
      });
    }
  }
});

可以看到這邊我們先試著從 local storage 去取得 x-token ,如果 token 存在,就把它加進 request 的 headers 。

另外登出非常簡單,直接清掉 local storage 的紀錄即可: localStorage.removeItem('x-token') ,當 token 消失後,使用者就只能再次登入得到新的 token 。

2. Authorization 方法

關於 Authorization 其實非常彈性,因為今天可能文章列表僅提供本人觀看、會員觀看或是供大眾觀看,但是新增文章、刪除文章一定都是本人才可以操作,因此這邊就會造成每個 component 的權限不盡相同,連帶就必須有策略地去做管理。

這邊我選擇使用 higher order function 來實作,分為 WithUserRequireAuth ,兩著皆會使用 query 搭配 local storage 的 token 去取得目前登入者資訊。

query CurrentUser {
  me {
    id
    name
    email
  }
}

WithUser 可以讓 wrapped component 從 props.user 得到目前登入者的資訊 ; 而 RequireAuthWithUser 一樣,只是如果沒有得到登入者資料 (沒有 token 或 token 不合法),就會直接強制轉到登入畫面。

舉個例子,我接下來會新增一個 Header Component ,當使用者尚未登入時,就會顯示 "Signup" 與 "Login" 兩個按鈕,而如果使用者已經登入了,則是顯示 "Logout" 按鈕,這邊就會用到 WithUser 來判斷顯示方式。而且像是刪除文章的按鈕也是需要 WithUser 傳入已登入使用者資訊來判斷是否顯示。

再來,像是新增文章頁面,就一定要得是已登入使用者才可以訪問,因此會用到 RequireAuth 來幫忙判斷,如果尚未登入就應該直接跳到登入頁面~


Reference


上一篇
GraphQL 前端 (2) - 文章按讚及刪除文章
下一篇
GraphQL 前端 (4) - 部落格系統 Demo + 小結
系列文
Think in GraphQL30

尚未有邦友留言

立即登入留言