首頁 » 面試題庫 » 後端 » 身份驗證機制 – 後端工程師面試問題彙總-20240515

最近OpenAI推出了GPT-4o模型,用AI整理了些後端工程師在技術面試時可能會遇到的問題。依等級分為入門級(Beginner)、初級(Junior)、中級(Intermediate)及高級(Senior),也有分散式任務及身份驗證機制專章。答案僅供參考,請搭配其他資料服用。

本篇為身份驗證機制專章:

目錄

初級(Junior)

1. 請簡單描述什麼是Stateless特性,為什麼RESTful API需要這個特性?

  • Stateless特性指的是每個HTTP請求是獨立的且無狀態的,伺服器不會在多個請求之間保存客戶端的狀態。這意味着所有的狀態信息必須由客戶端提供,每個請求都應包含完成所需的所有信息。
  • 這使得系統更具可擴展性,因為不需要在伺服器端保存狀態信息,從而可以輕鬆擴展處理更多的請求。

2. 列出並簡要説明三種常見的基於RESTful API的身份驗證方法。

  • API Key:客戶端在每個請求中包含一個唯一的API Key,服務器根據這個Key來驗證身份。
  • Basic Authentication:客戶端在HTTP標頭中包含基本的用戶名和密碼進行驗證。
  • Bearer Token(如JWT):客戶端在每個請求的HTTP標頭中包含一個JWT Token,服務器根據這個Token來驗證身份。

3. 什麼是Basic Auth,如何在RESTful API中實現?請提供基本流程。

  • Basic Auth是一種簡單的身份驗證方法,客戶端用戶名和密碼以Base64編碼後被添加到HTTP標頭。
  • 基本流程:
    • 客戶端將用戶名和密碼以username:password格式拼接,然後使用Base64編碼。
    • 將編碼後的字串添加到HTTP標頭中的Authorization字段,如Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=
    • 伺服器解碼後驗證用戶名和密碼。

4. 請解釋什麼是Bearer Token,在哪種情況下會使用Bearer Token?

  • Bearer Token是一種憑證,通常用於OAuth 2.0標準中進行身份驗證。使用Bearer Token時,客戶端在HTTP請求的Authorization標頭中包含該Token,如Authorization: Bearer <token>。這種方法適用於需要較高安全性和靈活性的應用場景。

5. 什麼是API Key,如何使用API Key進行身份驗證?

  • API Key是一個唯一的標識符,由伺服器生成並分發給客戶端,用於標識和授權API請求。
  • 範例:
GET /some-endpoint HTTP/1.1
Host: api.example.com
Authorization: ApiKey <your_api_key>

中級(Intermediate)

1. 請比較API Key、Basic Auth和Bearer Token(如JWT)這三種身份驗證方法的優缺點。

  • API Key
    • 優點:實現簡單,易於管理。
    • 缺點:安全性較低,容易被竊取,無需加密。
  • Basic Auth
    • 優點:實現簡單,所有HTTP客戶端都支持。
    • 缺點:每次請求都需要傳遞用戶名和密碼,存在較大的安全風險,通常需要SSL加密。
  • Bearer Token(如JWT)
    • 優點:高度安全,可攜帶自定義聲明(claims),支持無狀態,適合分布式系統。
    • 缺點:需要管理Token的發放和過期,Token可能被盜取。

2. 在Django中,如何實現API Key身份驗證?請提供具體步驟和代碼範例。

步驟

安裝djangorestframework-api-key

pip install djangorestframework-api-key

Django設定

# settings.py
INSTALLED_APPS = [
    ...
    'rest_framework',
    'rest_framework_api_key',
]

建立API Key模型:

from rest_framework_api_key.models import APIKey

api_key, key = APIKey.objects.create_key(name="my-key")
print(key)  # 顯示API Key

在views.py中使用API Key身份驗證:

# views.py
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework_api_key.permissions import HasAPIKey

class MyAPIView(APIView):
    permission_classes = [HasAPIKey]

    def get(self, request):
        return Response({"message": "Hello, world!"})

3. 什麼是JWT(JSON Web Token),為什麼它經常用於RESTful API的身份驗證?

  • JWT(JSON Web Token)是一種開放標準(RFC 7519),用於在各方之間傳輸聲明,特別是用於身份驗證和信息交換。
  • 為什麼經常用於RESTful API的身份驗證
    • 安全性高:簽名確保數據未被篡改。
    • 無狀態:JWT自包含相關信息,伺服器無需存儲會話狀態。
    • 可攜帶自定義聲明:可以靈活傳遞用戶和訪問控制信息。

4. 請詳細解釋JWT的結構,它是如何實現身份驗證的?

  • JWT結構
    • Header:包含Token的類型(即JWT)和簽名算法(如HMAC SHA256)。
    • Payload:包含聲明(claims),即傳遞的信息,如用戶ID和過期時間。
    • Signature:用於驗證信息未被篡改,使用頭部中指定的簽名算法和密鑰。
  • 實現過程
    1. 當用戶成功登錄時,伺服器生成JWT並返回給用戶。
    2. 用戶在後續請求中將JWT作為Authorization標頭的一部分發送。
    3. 伺服器驗證JWT的簽名和有效性,確定用戶身份。

5. 請描述如何在Django REST框架中實現JWT身份驗證,並提供代碼示例。

步驟

安裝djangorestframework-simplejwt

pip install djangorestframework-simplejwt

Django settings.py

# settings.py
INSTALLED_APPS = [
    ...
    'rest_framework',
    'rest_framework_simplejwt',
]

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework_simplejwt.authentication.JWTAuthentication',
    ),
}

from datetime import timedelta

SIMPLE_JWT = {
    'ACCESS_TOKEN_LIFETIME': timedelta(minutes=5),
    'REFRESH_TOKEN_LIFETIME': timedelta(days=1),
}

設置URL

# urls.py
from django.urls import path
from rest_framework_simplejwt.views import (
    TokenObtainPairView,
    TokenRefreshView,
)

urlpatterns = [
    path('api/token/', TokenObtainPairView.as_view(), name='token_obtain_pair'),
    path('api/token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
]

建立受保護的view

# views.py
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated

class MyProtectedView(APIView):
    permission_classes = [IsAuthenticated]

    def get(self, request):
        return Response({"message": "This is a protected view"})

6. 在使用Bearer Token進行身份驗證時,應如何實現Token的過期和刷新機制?請提供具體步驟。

  1. 使用JWT中的閾限時間(expiration time, exp)來設置Token過期時間。
  2. 當Token過期後,用戶可以使用Refresh Token來獲得新的Access Token。
  3. 在Django中,通過djangorestframework-simplejwt來實現這一機制。
# 配置刷新Token的視圖
from rest_framework_simplejwt.views import (
    TokenObtainPairView,
    TokenRefreshView,
)

urlpatterns = [
    path('api/token/', TokenObtainPairView.as_view(), name='token_obtain_pair'),
    path('api/token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
]

# 配置刷新Token的過期時間
from datetime import timedelta

SIMPLE_JWT = {
    'ACCESS_TOKEN_LIFETIME': timedelta(minutes=5),
    'REFRESH_TOKEN_LIFETIME': timedelta(days=1),
}

7.請說明Bearer Token在OAuth 2.0標準中的應用,並描述如何在Django中實現它。

  • 應用
    • Bearer Token通常在OAuth 2.0標準中用於攜帶用戶的授權憑證,以確保用戶的身份驗證。
    • 客戶端請求OAuth 2.0認證服務器以獲取Access Token,然後將這個Token包含在每次API請求的HTTP標頭中。
  • Django實現

安裝djangorestframework-simplejwt

pip install djangorestframework-simplejwt

Django settings.py

# settings.py
INSTALLED_APPS = [
    ...
    'rest_framework',
    'rest_framework_simplejwt',
]

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework_simplejwt.authentication.JWTAuthentication',
    ),
}

from datetime import timedelta

SIMPLE_JWT = {
    'ACCESS_TOKEN_LIFETIME': timedelta(minutes=5),
    'REFRESH_TOKEN_LIFETIME': timedelta(days=1),
}

設置URL

# urls.py
from django.urls import path
from rest_framework_simplejwt.views import (
    TokenObtainPairView,
    TokenRefreshView,
)

urlpatterns = [
    path('api/token/', TokenObtainPairView.as_view(), name='token_obtain_pair'),
    path('api/token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
]

創建受保護的視圖

# views.py
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated

class MyProtectedView(APIView):
    permission_classes = [IsAuthenticated]

    def get(self, request):
        return Response({"message": "This is a protected view"})

8. 在一個高併發環境中,如何確保API身份驗證的安全性並降低服務器負載?

  • 使用TLS:確保所有數據傳輸加密,避免中間人攻擊。
  • 短期Token和刷新Token:使用有效期較短的Access Token和高安全性存儲的Refresh Token,減少長期有效Token被盜用的風險。
  • Token緩存:利用分布式緩存(如Redis)來儲存和查驗Token的狀態,加快驗證速度。
  • 限制請求速率:實施速率限制(Rate Limiting)機制,防止暴力破解和DoS攻擊。
  • 批量操作:實現批量API以減少頻繁的API請求,降低伺服器負載。
  • 監控和警報:使用監控工具(如Prometheus和Grafana)監控API請求和異常行為,及時發現並處理潛在的安全問題。

高級(Senior)

1. 請詳細比較OAuth 1.0和OAuth 2.0的主要區別和優缺點。

  • OAuth 1.0
    • 主要特點:基於簽名(Signature)的驗證方法,使用多步驟流程。
    • 優點:安全性較高,簽名驗證防止請求被竄改。
    • 缺點:實現和使用相對複雜,需要多次請求-回應流程。
  • OAuth 2.0
    • 主要特點:簡化了簽名流程,支持多種授權方式(授權碼、隱藏模式、密碼模式、客戶端憑證)。
    • 優點:更靈活,易於使用和擴展,適合web、移動和桌面應用。
    • 缺點:部分授權方式安全性相對較低,需要額外的安全措施(如使用HTTPS)。

2. 請解釋OAuth 2.0的四種授權方式

  • 授權碼模式(Authorization Code Grant)
    • 應用場景:標準的web應用,用戶需要瀏覽器進行登錄。
    • 安全性:最高,需要應用後台交換授權碼,以避免Token泄露。
  • 隱藏模式(Implicit Grant)
    • 應用場景:單頁應用(SPA),無服務器端後台。
    • 安全性:較低,不推薦,Token直接暴露在URL中。
  • 密碼模式(Resource Owner Password Credentials Grant)
    • 應用場景:自有應用(如移動應用),用戶信任應用程序。
    • 安全性:中等,用戶密碼直接授權給應用,風險較高。
  • 客戶端憑證模式(Client Credentials Grant)
    • 應用場景:服務到服務的通信,無需用戶參與。
    • 安全性:合適,但要求客戶端安全存儲憑證。

3. 在分布式系統中,如何有效管理和驗證JWT,並確保多個服務器之間的會話一致性?具體實現策略為何。

  • 管理和驗證JWT的方法
    1. 集中認證服務(Authentication Service):通過單一點進行Token的生成和驗證,減少各服務認證的負擔。
    2. 使用緩存:使用分布式緩存(如Redis)來存儲和檢查Token的有效性和狀態。
    3. 設置Token過期時間:確保Token有明確的有效期,減少長期有效的安全風險。
    4. 定期檢查和黑名單:檢查Token的JwtId(jti)是否在黑名單中,避免被吊銷的Token被繼續使用。
  • 確保會話一致性
    1. 同步Token狀態:在多個服務器間同步Token狀態,使用分布式數據庫或消息隊列。
    2. 使用分布式鎖:確保一個Token的狀態更新只由一個實例負責,防止數據不一致。
  • 具體實現策略:

配置JWT密鑰和過期時間

from datetime import timedelta
import os

SECRET_KEY = os.getenv('SECRET_KEY', 'your-secret-key')

JWT_CONFIG = {
    'ACCESS_TOKEN_LIFETIME': timedelta(minutes=15),
    'REFRESH_TOKEN_LIFETIME': timedelta(days=1),
    'ALGORITHM': 'HS256',
    'SIGNING_KEY': SECRET_KEY,
}

在認證服務中集中管理和驗證JWT

from jose import jwt

def create_jwt(payload, config):
    return jwt.encode(payload, config['SIGNING_KEY'], algorithm=config['ALGORITHM'])

def verify_jwt(token, config):
    try:
        payload = jwt.decode(token, config['SIGNING_KEY'], algorithms=[config['ALGORITHM']])
        return payload
    except jwt.JWTError:
        return None

實現黑名單機制

blacklisted_tokens = set()

def blacklist_token(token):
    blacklisted_tokens.add(token)

def is_token_blacklisted(token):
    return token in blacklisted_tokens

4. Token滲透攻擊是什麼?如何防止JWT被滲透?

  • Token滲透攻擊:攻擊者獲取有效的Token後,冒充合法用戶執行未經授權的操作或訪問敏感數據。
  • 防止方法
    • 使用HTTPS:確保所有請求和響應都經過加密。
    • 合理設置過期時間:減少Token長期存在的風險。
    • 定期輪換密鑰:定期更改簽名密鑰,防止長時間使用同一密鑰。
    • 當前IP確認:在Token載荷中包含請求的IP地址,並在伺服器端進行驗證。
    • 實施雙因子認證(2FA):提高用戶認證的安全性。

5. 基於JWT的身份驗證有什麼潛在的安全風險?如何在設計中減少這些風險?

  • 潛在風險
    1. Token泄露:Token可能在傳輸或存儲過程中被盜用。
    2. Token未過期:長期有效的Token容易被攻擊者利用。
    3. Token重放攻擊:使用被竊取的Token重複發送請求。
  • 減少風險的設計策略
    1. HTTPS加密:確保所有通信過程中使用HTTPS加密。
    2. 短期Token和刷新Token:設置短期有效期的Access Token和定期更換的Refresh Token。
    3. Token黑名單:在登出或Token被認可為無效時將其添加到黑名單。
    4. 雙因子認證(2FA):加入額外的身份驗證因素,提高安全性。
    5. 使用Claims:在Token中添加用戶IP、客戶端信息等來驗證Token的有效性。

6. 請描述在多租戶應用中,如何設計身份驗證系統來有效管理和保護不同租戶的數據。

  • 設計考量
    • 租戶隔離:確保一個租戶的數據不能被其他租戶訪問。
    • 標識租戶:在Token或用戶身份中包含租戶標識,以區分請求屬於哪個租戶。
    • 訪問控制:根據租戶和角色設置不同的訪問權限。
  • 實現策略

對每個請求進行租戶認證

def get_tenant_from_token(token):
    payload = verify_jwt(token)
    if payload:
        return payload.get('tenant_id')
    return None

在數據訪問層根據租戶ID進行隔離

def get_user_data(user_id, tenant_id):
    return User.objects.filter(id=user_id, tenant_id=tenant_id)

設置權限控制

from rest_framework.permissions import BasePermission

class IsTenantUser(BasePermission):
    def has_permission(self, request, view):
        tenant_id = get_tenant_from_token(request.auth)
        return request.user.tenant_id == tenant_id

7. 在Django REST框架中,如何實現基於角色的訪問控制(RBAC)?請提供具體實現方法和代碼示例。

創建角色模型

# models.py
from django.contrib.auth.models import AbstractUser
from django.db import models

class Role(models.Model):
    name = models.CharField(max_length=50)
    permissions = models.ManyToManyField('Permission', blank=True)

class User(AbstractUser):
    roles = models.ManyToManyField(Role, blank=True)

定義角色和權限

# permissions.py
from rest_framework.permissions import BasePermission

class HasRolePermission(BasePermission):
    def has_permission(self, request, view):
        required_roles = getattr(view, 'required_roles', [])
        user_roles = request.user.roles.all()
        if not required_roles:
            return True
        return any(role.name in required_roles for role in user_roles)

在視圖中使用角色驗證

# views.py
from rest_framework.views import APIView
from .permissions import HasRolePermission

class AdminView(APIView):
    permission_classes = [HasRolePermission]
    required_roles = ['admin']

    def get(self, request):
        return Response({"message": "Admin view"})

設置URL

# urls.py
from django.urls import path
from .views import AdminView

urlpatterns = [
    path('admin/', AdminView.as_view(), name='admin_view'),
]

8. 在設計一個RESTful API的身份驗證機制時,如何平衡安全性與性能呢?請描述你會考慮的因素和策略。

  1. 使用短期Token和刷新Token:保證較高的安全性,並降低頻繁的認證開銷。
  2. 高效的加密算法:選擇速度相對較快且安全性高的加密算法,平衡加解密時間和安全性。
  3. 集中式驗證服務:集中進行身份驗證,減少各服務之間的驗證負擔。
  4. Token緩存:使用緩存機制(如Redis)存儲Token的狀態,減少對資料庫的頻繁訪問。
  5. 負載均衡:利用負載均衡將請求分發到多個伺服器,減少單個伺服器的壓力。
  6. 監控和限流:實施監控和限流策略,防止暴力破解和DDoS攻擊。


One Reply to “身份驗證機制 – 後端工程師面試問題彙總-20240515”

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *