快轉到主要內容

實作 Google OAuth 第三方登入 整合到會員登入系統

·
類別 
前端開發 後端開發
標籤 
Vue Google Oauth
Eason Chiu
作者
Eason Chiu
一個不做筆記就容易忘記的工程師
目錄

前言
#

本篇主要介紹如何實作 Google OAuth 第三方登入,下面的實作是基於現有的會員系統上整合第三方登入,關於之前的會員登入系統部分可以參考這篇:《Docker 部署 Spring Boot + Vue + PostgreSQL 實現一個會員註冊登入系統》。有鑒於那篇真的太冗長了,本編將 著重於 Google OAuth 的設定

  • 使用者的透過 Google 帳號登入註冊流程非常簡單,流程如下:
  1. 進到登入畫面,選擇 使用 Google 帳戶登入
  2. 選擇登入的 Google 帳號。
  3. 並允許個人資料授權。
  4. 系統就會綁定 Google 帳號進行登入。

Google OAuth 整合流程
#

在下方的流程圖中,簡單說明了用戶從點擊 Google 登入按鈕,到最終登入成功的整個流程。這個流程包含 前端初始化 Google 登入用戶授權後端驗證 ID Token查詢或創建用戶資料,並最終回傳 JWT Token 給前端,完成登入。整個過程大致如下:

sequenceDiagram participant U as 用戶 participant F as 前端 (Vue) participant G as Google 服務 participant B as 後端 (Spring Boot) participant DB as PostgreSQL U->>F: 1. 點擊 Google 登入 F->>G: 2. 初始化 Google Sign-In G->>U: 3. 顯示 Google 授權頁面 U->>G: 4. 選擇帳號並授權 G->>F: 5. 返回 ID Token F->>B: 6. POST /api/auth/google-login B->>G: 7. 驗證 ID Token G->>B: 8. 返回用戶資訊 B->>DB: 9. 查詢/創建用戶 B->>F: 10. 返回 JWT Token F->>U: 11. 登入成功

系統實作
#

Google OAuth 設定
#

  1. 前往 Google Cloud Console
  2. 展開側邊欄點選 API和服務,選擇 OAuth 同意畫面
  3. 輸入 應用程式名稱使用者支援電子郵件 這裡填寫的郵件,會顯示在開發人員資訊上
  4. 選擇 外部 目標對象。
  5. 填寫負責人員的電子郵件地址。
  6. 同意 Google API 條款。
  7. 按下建立後會出現 OAuth 總覽 , 點擊 建立 OAuth 用戶端
  8. 選擇 網頁應用程式 類型。
  9. 填入 名稱,以及 JavaScripte來源重新導向URL。 測試網址填入:http://localhost ,到時候有了正式網域後再添加上去。
  10. 按下 建立 後,就會得到 用戶端ID用戶端密碼

前端實作
#

前端 Vue 頁面需要整合 Google Identity Services,前端只需要處理回調,複雜的驗證邏輯交給 Google,實作的部分,主要包含三個步驟:

1. 初始化 Google Identity Services
#

動態載入 Google Identity Services 的 JavaScript 函式庫,確保在需要時才載入,避免影響頁面初始載入速度,只有當用戶真的想用 Google 登入時才載入相關資源。

  • 範例程式碼
typescript
// 載入 Google Identity Services 腳本
const loadGoogleScript = (): Promise<void> => {
  return new Promise((resolve, reject) => {
    if (window.google) {
      resolve()
      return
    }
    
    const script = document.createElement('script')
    script.src = 'https://accounts.google.com/gsi/client'
    script.async = true
    script.defer = true
    script.onload = () => resolve()
    script.onerror = () => reject(new Error('Failed to load Google script'))
    document.head.appendChild(script)
  })
}

2. 初始化 Google Sign-In
#

這裡只需要前面在 Google Cloud Console 上取得的 用戶端ID 帶到 YOUR_GOOGLE_CLIENT_ID。設定好後,Google 就會自動幫我們渲染出登入按鈕,而且會根據用戶的語言環境自動調整顯示文字。

  • 範例程式碼
typescript
// 初始化 Google Sign-In
onMounted(async () => {
    await loadGoogleScript()
    if (window.google) {
      window.google.accounts.id.initialize({
      client_id: 'YOUR_GOOGLE_CLIENT_ID',
        callback: handleGoogleCallback,
        auto_select: false,
        cancel_on_tap_outside: true,
        context: 'signin'
      })
      
      // 渲染 Google 登入按鈕
      const buttonContainer = document.getElementById('google-signin-button')
      if (buttonContainer) {
        window.google.accounts.id.renderButton(buttonContainer, {
          theme: 'outline',
          size: 'large',
          text: 'signin_with',
          shape: 'rectangular',
        width: '100%'
      })
    }
  }
})

3. Google 登入回調處理
#

當用戶完成 Google 授權後,會收到包含 credential 的回調,這個 credential 就是 Google 給我們的 ID Token。

credential 是一個 JWT (JSON Web Token) 格式的字串,包含以下欄位:

  • sub:Google 用戶的唯一 ID(來源:Google 帳號系統)
  • email:用戶的 Google 信箱(來源:Google 帳號資料)
  • name:用戶的顯示名稱(來源:Google 個人資料)
  • picture:用戶的頭像 URL(來源:Google 個人資料)
  • email_verified:信箱是否已驗證(來源:Google 驗證狀態)
  • aud:Client ID(用於驗證,來源:Google Cloud Console 設定)
  • iss:發行者(固定為 “https://accounts.google.com”)
  • exp:Token 過期時間(來源:Google 自動生成)
  • iat:Token 發行時間(來源:Google 自動生成)
  • azp:授權方(Client ID,來源:Google Cloud Console 設定)

格式文件參考:

我們把這個 ID Token 發送給後端,後端會向 Google 的 tokeninfo API 驗證這個 Token 是否有效,Google 會回傳用戶的詳細資訊。後端拿到這些資訊後,會檢查用戶是否已存在,如果 不存在就創建新用戶,最後回傳我們系統的 JWT Token 給前端,整個流程就完成了。

  • 範例程式碼
typescript
// Google 登入回調處理
const handleGoogleCallback = async (response: any) => {
  const result = await fetch('/api/auth/google-login', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ idToken: response.credential })
  })
  
  const data = await result.json()
  if (result.ok && data.success) {
    AuthUtils.setAuth(data.token, data.refreshToken, data.user, true)
    router.push('/')
  }
}

後端實作
#

後端主要接收的 API:

  • POST /api/auth/google-login:接收前端傳來的 Google ID Token
  • Service 的部分建立 GoogleOAuthService 來處理 Google Token 驗證

實作主要包含三個核心功能:

1. Google Token 驗證
#

後端接收到前端傳來的 Google ID Token 後,會向 Google 的 tokeninfo API 發送驗證請求,獲取用戶資訊並驗證 Token 的有效性。

java
String url = "https://oauth2.googleapis.com/tokeninfo?id_token=" + idToken;
ResponseEntity<Map> response = restTemplate.getForEntity(url, Map.class);

同時檢查 audience 欄位確保 Token 是為我們的應用程式發行的,防止偽造攻擊。

java
// 驗證 audience (client ID)
Map<String, Object> userInfo = (Map<String, Object>) response.getBody();
String audience = (String) userInfo.get("aud");
if (!clientId.equals(audience)) {
    result.put("success", false);
    result.put("message", "無效的 Google Token");
    return result;
}

String googleId = (String) userInfo.get("sub");
String email = (String) userInfo.get("email");
String name = (String) userInfo.get("name");
String picture = (String) userInfo.get("picture");
Object emailVerifiedObj = userInfo.get("email_verified");

2. 用戶管理與綁定
#

當用戶透過 Google 登入時,會先檢查是否已有對應的 Google 用戶記錄。如果找到就直接登入。 如果沒有找到,系統會嘗試透過電子郵件查找現有的系統用戶:

  • 電子郵件已經註冊 過,就會將 Google 帳號綁定到現有用戶。
  • 沒有註冊過 的新用戶,系統會自動創建新的用戶記錄,並標記為 Google 用戶。
flowchart LR A[用戶點擊 Google 登入] --> B[接收 Google ID Token] B --> D{找到 Google 用戶?} D -- 是 --> L[登入成功] D -- 否 --> G[findByEmail 查找系統用戶?] G -- 是 --> H[綁定 Google 帳號到現有用戶] G -- 否 --> I[創建新的 Google 用戶] H --> L I --> L

findByEmail 透過 Google 帳號的電子郵件地址查找現有的系統用戶。這個方法主要處理現有系統用戶綁定 Google 登入的情況,當系統發現該電子郵件已經在系統中註冊過,就會將 Google 帳號資訊綁定到現有用戶

  • 一般註冊用戶

一般用戶是透過帳號密碼進行登入的,所以擁有修改密碼的功能。

  • Google註冊用戶

透過 Google 進行綁定登入的用戶,直接透過 Google 驗證做登入,就不需要修改密碼的功能了。 綁定Google帳戶 後,就無法再透過一般帳密做登入了, 驗證登入交給 Google,對於系統面的考量來說安全性也較高

3. JWT Token 生成
#

驗證成功後生成系統的 JWT TokenRefresh Token,並將用戶資訊回傳給前端,確保 Google 登入用戶與一般用戶享有相同的驗證 Token

資料庫調整
#

在之前的會員 users 表中新增 Google OAuth 相關欄位:

  • google_id:Google 使用者 ID
  • google_email:Google 帳號電子郵件
  • is_google_user:是否為 Google 註冊用戶
  • google_picture_url:Google 帳號頭像 URL

並建立相應的索引和查詢方法來支援 Google 用戶的查找和綁定。

結語
#

透過整合 Google OAuth,成功實現了第三方登入功能,大幅提升了用戶註冊登入的便利性,可直接使用現有的 Google 帳號登入,簡單又方便的註冊管道,可提高顧客加入會員的意願,同時也能減少忘記密碼等問題。

相關文章

Docker 部署 Spring Boot + Vue + PostgreSQL 實現一個會員註冊登入系統
類別 
前端開發 後端開發
標籤 
Vue Spring-Boot Jwt Postgresql Docker
Html2canvas + Fabricjs 應用
類別 
前端開發
標籤 
Html2canvas Fabricjs
使用Can I Use 檢查瀏覽器相容性
類別 
前端開發
標籤 
Browser