[golang]關於 Golang API 開發 中,權限管理(Authorization)

 Golang API 開發 中,權限管理(Authorization) 是一個關鍵的部分,確保只有符合條件的使用者或系統能夠存取特定資源。一般來說,權限管理的方式包括:

  1. 基於角色的存取控制(RBAC, Role-Based Access Control)
  2. 基於屬性的存取控制(ABAC, Attribute-Based Access Control)
  3. JWT(JSON Web Token)驗證
  4. OAuth 2.0 & OpenID Connect
  5. API 金鑰驗證(API Key)

以下是各種權限管理方式的詳細說明與 Golang 實作範例:



1. 基於角色的存取控制(RBAC)

RBAC(Role-Based Access Control) 是最常見的權限管理方式,根據使用者的「角色」來決定是否授權存取 API。

RBAC 權限架構

    • 使用者(User):代表 API 的訪客或系統帳號
    • 角色(Role):如 adminusereditor
    • 權限(Permission):對應 API 的存取權限,如 readwritedelete

RBAC 中間件實作

package main import (
"fmt"
"net/http"
) // 假設我們有一個角色對應的權限
var rolePermissions = map[string][]string{
"admin": {"read", "write", "delete"},
"user": {"read"},
} // 模擬取得使用者角色的函式(通常來自 JWT 或資料庫)
func getUserRole(r *http.Request) string {
// 這裡假設從 Header 取得使用者角色
return r.Header.Get("Role")
} // 權限檢查中間件
func PermissionMiddleware(requiredPermission string, next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
userRole := getUserRole(r)
// 取得該角色的權限
permissions, exists := rolePermissions[userRole]
if !exists {
http.Error(w, "Unauthorized", http.StatusUnauthorized)
return
}
// 檢查角色是否擁有所需權限
for _, perm := range permissions {
if perm == requiredPermission {
next.ServeHTTP(w, r)
return
}
} http.Error(w,
http.Error(w, "Forbidden", http.StatusForbidden)
})
} func main() {
mux := http.NewServeMux()
// 受保護的 API 只允許擁有 "read" 權限的角色存取
mux.Handle("/protected", PermissionMiddleware("read", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "這是一個受保護的 API")
}))) http.ListenAndServe(
http.ListenAndServe(":8080", mux)
}

測試

假設啟動服務後,使用 curl 測試:

curl -H "Role: user" http://localhost:8080/protected

如果是 user 角色,就會成功存取;如果角色沒有 read 權限,則會被拒絕。



2. 基於屬性的存取控制(ABAC)

ABAC(Attribute-Based Access Control) 透過「使用者、資源、環境」等多個屬性來決定是否授權,適用於更細緻的權限控制。

舉例:只有 部門經理 且 IP 在公司內部網段 才能存取某 API。

func ABACMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
userRole := getUserRole(r)
clientIP := r.RemoteAddr // 假設從這裡取 IP
// 例:部門經理 & IP 來自內部網段,才能存取
if userRole == "manager" && clientIP == "192.168.1.100" {
next.ServeHTTP(w, r)
return
} http.Error(w,
http.Error(w, "Forbidden", http.StatusForbidden)
})
}


3. JWT(JSON Web Token)驗證

JWT 是 API 身份驗證中最常用的方法,透過 Token 來識別使用者身份,並附帶角色資訊。

步驟

    1. 登入 API 回傳 JWT Token
    2. 使用者請求 API 時,攜帶 JWT Token
    3. 後端驗證 JWT,並解析角色資訊

JWT Middleware 實作

需要使用 github.com/golang-jwt/jwt/v5

package main import (
"fmt"
"net/http"
"strings"
"github.com/golang-jwt/jwt/v5"
) var jwtKey = []byte("secret_key") // 這裡應該用環境變數設定 // JWT 驗證中間件
func JWTMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
authHeader := r.Header.Get("Authorization")
if authHeader == "" {
http.Error(w, "Missing token", http.StatusUnauthorized)
return
} tokenString := strings.TrimPrefix(authHeader,
tokenString := strings.TrimPrefix(authHeader, "Bearer ") claims := &jwt.RegisteredClaims{}
token, err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (interface{}, error) {
return jwtKey, nil
})
if err != nil || !token.Valid {
http.Error(w, "Invalid token", http.StatusUnauthorized)
return
}
fmt.Println("Authenticated user:", claims.Subject) // 解析 JWT 內的 user 資訊
next.ServeHTTP(w, r)
})
}

前端請求時加上 Authorization: Bearer <JWT Token>,後端解析後就能獲取用戶資訊。



4. OAuth 2.0 & OpenID Connect

如果 API 需要整合 Google、Facebook、GitHub 登入,可以使用 OAuth 2.0 或 OpenID Connect。

在 Golang 中,可使用 golang.org/x/oauth2 套件來處理 OAuth 驗證。

import "golang.org/x/oauth2"

(此方式較複雜,適用於 第三方登入,通常與 JWT 配合使用)



5. API 金鑰驗證

有些 API(如外部 API 或無狀態服務)會使用 API Key 來管理存取權限。

在 Header 中傳遞 API-Key,後端驗證 Key 是否有效。

func APIKeyMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
apiKey := r.Header.Get("API-Key")
if apiKey != "my-secret-key" {
http.Error(w, "Forbidden", http.StatusForbidden)
return
}
next.ServeHTTP(w, r)
})
}


結論

  • RBAC:適用於角色管理(Admin、User 等)。
  • ABAC:適用於需要更細膩條件(如 IP 限制、時間限制)。
  • JWT:適用於身份驗證,適合 無狀態 API
  • OAuth 2.0:適用於 第三方身份驗證(Google/Facebook 登入)
  • API Key:適用於 外部服務存取 API

留言

這個網誌中的熱門文章

[Kotlin]如何學習Kotlin

[golang]如何使用 gorm 高效執行批量插入 (可以透過 Create()、CreateInBatches(),或者 原生 SQL 語句 來提升效率)

[Kotlin]Kotlin Multiplatform (KMP) 如何安裝使用和部署