2.3 曝光!大厂都是这样设计API安全策略的!

1 阅读10分钟

2.3 曝光!大厂都是这样设计API安全策略的!

在构建高可用、高安全性的通知平台时,API安全策略是至关重要的一环。无论是防止恶意攻击、保护敏感数据,还是确保系统的稳定运行,都需要一套完善的安全机制。本节将深入探讨大厂常用的API安全策略设计方法,并提供实际的Go代码实现。

API安全的核心要素

API安全策略通常包括以下几个核心要素:

  1. 身份认证(Authentication):确认用户身份的真实性
  2. 权限授权(Authorization):确定用户是否有权限访问特定资源
  3. 数据加密(Encryption):保护数据在传输和存储过程中的安全
  4. 访问控制(Access Control):限制用户对资源的访问方式和频率
  5. 安全审计(Security Audit):记录和监控安全相关事件

身份认证机制

JWT(JSON Web Token)认证

JWT是一种开放标准(RFC 7519),用于在各方之间安全地传输信息。它由三部分组成:头部(Header)、载荷(Payload)和签名(Signature)。

// JWTAuth JWT认证器
type JWTAuth struct {
    // 签名密钥
    secretKey []byte
    
    // 令牌过期时间
    expireDuration time.Duration
}

// Claims JWT声明
type Claims struct {
    // 业务方ID
    BizID string `json:"biz_id"`
    
    // 权限列表
    Permissions []string `json:"permissions"`
    
    // 注册的标准声明
    jwt.StandardClaims
}

// NewJWTAuth 创建JWT认证器
func NewJWTAuth(secretKey string, expireDuration time.Duration) *JWTAuth {
    return &JWTAuth{
        secretKey:      []byte(secretKey),
        expireDuration: expireDuration,
    }
}

// GenerateToken 生成JWT令牌
func (ja *JWTAuth) GenerateToken(bizID string, permissions []string) (string, error) {
    // 设置令牌过期时间
    expirationTime := time.Now().Add(ja.expireDuration)
    
    // 创建声明
    claims := &Claims{
        BizID:       bizID,
        Permissions: permissions,
        StandardClaims: jwt.StandardClaims{
            ExpiresAt: expirationTime.Unix(),
            IssuedAt:  time.Now().Unix(),
            Issuer:    "notification-platform",
        },
    }
    
    // 创建令牌
    token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
    
    // 签名令牌
    tokenString, err := token.SignedString(ja.secretKey)
    if err != nil {
        return "", fmt.Errorf("failed to sign token: %w", err)
    }
    
    return tokenString, nil
}

// ValidateToken 验证JWT令牌
func (ja *JWTAuth) ValidateToken(tokenString string) (*Claims, error) {
    claims := &Claims{}
    
    // 解析令牌
    token, err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (interface{}, error) {
        // 验证签名方法
        if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
            return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
        }
        return ja.secretKey, nil
    })
    
    if err != nil {
        return nil, fmt.Errorf("failed to parse token: %w", err)
    }
    
    // 验证令牌有效性
    if !token.Valid {
        return nil, fmt.Errorf("invalid token")
    }
    
    // 检查是否过期
    if claims.ExpiresAt < time.Now().Unix() {
        return nil, fmt.Errorf("token expired")
    }
    
    return claims, nil
}

// RefreshToken 刷新JWT令牌
func (ja *JWTAuth) RefreshToken(tokenString string) (string, error) {
    claims, err := ja.ValidateToken(tokenString)
    if err != nil {
        return "", fmt.Errorf("invalid token: %w", err)
    }
    
    // 生成新的令牌
    newToken, err := ja.GenerateToken(claims.BizID, claims.Permissions)
    if err != nil {
        return "", fmt.Errorf("failed to generate new token: %w", err)
    }
    
    return newToken, nil
}

OAuth 2.0认证

OAuth 2.0是一种授权框架,允许第三方应用在用户授权的情况下访问用户资源,而无需获取用户的密码。

// OAuth2Auth OAuth2认证器
type OAuth2Auth struct {
    // 客户端存储
    clientStore ClientStore
    
    // 令牌存储
    tokenStore TokenStore
    
    // 配置
    config *OAuth2Config
}

// OAuth2Config OAuth2配置
type OAuth2Config struct {
    // 令牌过期时间
    AccessTokenExpire time.Duration
    
    // 刷新令牌过期时间
    RefreshTokenExpire time.Duration
    
    // 授权码过期时间
    AuthCodeExpire time.Duration
}

// Client 客户端信息
type Client struct {
    // 客户端ID
    ID string `json:"id" db:"id"`
    
    // 客户端密钥
    Secret string `json:"secret" db:"secret"`
    
    // 域名列表
    Domains []string `json:"domains" db:"domains"`
    
    // 重定向URL列表
    RedirectURLs []string `json:"redirect_urls" db:"redirect_urls"`
}

// Token 令牌信息
type Token struct {
    // 访问令牌
    AccessToken string `json:"access_token"`
    
    // 刷新令牌
    RefreshToken string `json:"refresh_token"`
    
    // 令牌类型
    TokenType string `json:"token_type"`
    
    // 过期时间(秒)
    ExpiresIn int64 `json:"expires_in"`
    
    // 业务方ID
    BizID string `json:"biz_id"`
    
    // 权限范围
    Scope string `json:"scope"`
    
    // 创建时间
    CreatedAt time.Time `json:"created_at"`
}

// ClientStore 客户端存储接口
type ClientStore interface {
    // GetClientByID 根据ID获取客户端
    GetClientByID(id string) (*Client, error)
    
    // ValidateClient 验证客户端
    ValidateClient(id, secret string) bool
}

// TokenStore 令牌存储接口
type TokenStore interface {
    // CreateToken 创建令牌
    CreateToken(token *Token) error
    
    // GetTokenByAccessToken 根据访问令牌获取令牌信息
    GetTokenByAccessToken(accessToken string) (*Token, error)
    
    // GetTokenByRefreshToken 根据刷新令牌获取令牌信息
    GetTokenByRefreshToken(refreshToken string) (*Token, error)
    
    // DeleteToken 删除令牌
    DeleteToken(accessToken string) error
}

// GenerateAccessToken 生成访问令牌
func (oa *OAuth2Auth) GenerateAccessToken(clientID, bizID, scope string) (*Token, error) {
    // 获取客户端信息
    client, err := oa.clientStore.GetClientByID(clientID)
    if err != nil {
        return nil, fmt.Errorf("failed to get client: %w", err)
    }
    
    // 生成访问令牌和刷新令牌
    accessToken := generateRandomString(32)
    refreshToken := generateRandomString(32)
    
    // 创建令牌
    token := &Token{
        AccessToken:  accessToken,
        RefreshToken: refreshToken,
        TokenType:    "Bearer",
        ExpiresIn:    int64(oa.config.AccessTokenExpire.Seconds()),
        BizID:        bizID,
        Scope:        scope,
        CreatedAt:    time.Now(),
    }
    
    // 保存令牌
    if err := oa.tokenStore.CreateToken(token); err != nil {
        return nil, fmt.Errorf("failed to save token: %w", err)
    }
    
    return token, nil
}

// RefreshAccessToken 刷新访问令牌
func (oa *OAuth2Auth) RefreshAccessToken(refreshToken string) (*Token, error) {
    // 获取旧令牌
    oldToken, err := oa.tokenStore.GetTokenByRefreshToken(refreshToken)
    if err != nil {
        return nil, fmt.Errorf("invalid refresh token: %w", err)
    }
    
    // 检查刷新令牌是否过期
    if time.Now().After(oldToken.CreatedAt.Add(oa.config.RefreshTokenExpire)) {
        // 删除过期令牌
        oa.tokenStore.DeleteToken(oldToken.AccessToken)
        return nil, fmt.Errorf("refresh token expired")
    }
    
    // 删除旧令牌
    if err := oa.tokenStore.DeleteToken(oldToken.AccessToken); err != nil {
        return nil, fmt.Errorf("failed to delete old token: %w", err)
    }
    
    // 生成新令牌
    newToken := &Token{
        AccessToken:  generateRandomString(32),
        RefreshToken: oldToken.RefreshToken, // 刷新令牌保持不变
        TokenType:    "Bearer",
        ExpiresIn:    int64(oa.config.AccessTokenExpire.Seconds()),
        BizID:        oldToken.BizID,
        Scope:        oldToken.Scope,
        CreatedAt:    time.Now(),
    }
    
    // 保存新令牌
    if err := oa.tokenStore.CreateToken(newToken); err != nil {
        return nil, fmt.Errorf("failed to save new token: %w", err)
    }
    
    return newToken, nil
}

// ValidateAccessToken 验证访问令牌
func (oa *OAuth2Auth) ValidateAccessToken(accessToken string) (*Token, error) {
    // 获取令牌
    token, err := oa.tokenStore.GetTokenByAccessToken(accessToken)
    if err != nil {
        return nil, fmt.Errorf("invalid access token: %w", err)
    }
    
    // 检查令牌是否过期
    if time.Now().After(token.CreatedAt.Add(oa.config.AccessTokenExpire)) {
        // 删除过期令牌
        oa.tokenStore.DeleteToken(token.AccessToken)
        return nil, fmt.Errorf("access token expired")
    }
    
    return token, nil
}

权限授权机制

RBAC(基于角色的访问控制)

RBAC是一种基于角色的访问控制模型,通过将权限分配给角色,再将角色分配给用户,实现权限管理。

// RBACAuth RBAC认证器
type RBACAuth struct {
    // 角色存储
    roleStore RoleStore
    
    // 用户角色存储
    userRoleStore UserRoleStore
    
    // 权限存储
    permissionStore PermissionStore
}

// Role 角色
type Role struct {
    // 角色ID
    ID string `json:"id" db:"id"`
    
    // 角色名称
    Name string `json:"name" db:"name"`
    
    // 描述
    Description string `json:"description" db:"description"`
}

// UserRole 用户角色
type UserRole struct {
    // 用户ID
    UserID string `json:"user_id" db:"user_id"`
    
    // 角色ID
    RoleID string `json:"role_id" db:"role_id"`
}

// Permission 权限
type Permission struct {
    // 权限ID
    ID string `json:"id" db:"id"`
    
    // 权限名称
    Name string `json:"name" db:"name"`
    
    // 资源
    Resource string `json:"resource" db:"resource"`
    
    // 操作
    Action string `json:"action" db:"action"`
    
    // 描述
    Description string `json:"description" db:"description"`
}

// RolePermission 角色权限
type RolePermission struct {
    // 角色ID
    RoleID string `json:"role_id" db:"role_id"`
    
    // 权限ID
    PermissionID string `json:"permission_id" db:"permission_id"`
}

// RoleStore 角色存储接口
type RoleStore interface {
    // GetRoleByID 根据ID获取角色
    GetRoleByID(id string) (*Role, error)
    
    // GetRolesByUserID 根据用户ID获取角色列表
    GetRolesByUserID(userID string) ([]*Role, error)
}

// UserRoleStore 用户角色存储接口
type UserRoleStore interface {
    // GetUserRolesByUserID 根据用户ID获取用户角色列表
    GetUserRolesByUserID(userID string) ([]*UserRole, error)
}

// PermissionStore 权限存储接口
type PermissionStore interface {
    // GetPermissionsByRoleID 根据角色ID获取权限列表
    GetPermissionsByRoleID(roleID string) ([]*Permission, error)
    
    // CheckPermission 检查用户是否具有指定权限
    CheckPermission(userID, resource, action string) (bool, error)
}

// CheckPermission 检查用户是否具有指定权限
func (ra *RBACAuth) CheckPermission(userID, resource, action string) (bool, error) {
    // 获取用户角色
    userRoles, err := ra.userRoleStore.GetUserRolesByUserID(userID)
    if err != nil {
        return false, fmt.Errorf("failed to get user roles: %w", err)
    }
    
    // 检查每个角色是否具有指定权限
    for _, userRole := range userRoles {
        permissions, err := ra.permissionStore.GetPermissionsByRoleID(userRole.RoleID)
        if err != nil {
            continue // 跳过出错的角色
        }
        
        for _, permission := range permissions {
            if permission.Resource == resource && permission.Action == action {
                return true, nil
            }
        }
    }
    
    return false, nil
}

// GetUserPermissions 获取用户权限列表
func (ra *RBACAuth) GetUserPermissions(userID string) ([]*Permission, error) {
    // 获取用户角色
    userRoles, err := ra.userRoleStore.GetUserRolesByUserID(userID)
    if err != nil {
        return nil, fmt.Errorf("failed to get user roles: %w", err)
    }
    
    // 收集权限
    permissionMap := make(map[string]*Permission)
    for _, userRole := range userRoles {
        permissions, err := ra.permissionStore.GetPermissionsByRoleID(userRole.RoleID)
        if err != nil {
            continue // 跳过出错的角色
        }
        
        for _, permission := range permissions {
            permissionMap[permission.ID] = permission
        }
    }
    
    // 转换为切片
    var result []*Permission
    for _, permission := range permissionMap {
        result = append(result, permission)
    }
    
    return result, nil
}

数据加密机制

HTTPS/TLS加密

HTTPS是HTTP的安全版本,通过TLS/SSL协议对传输数据进行加密。

// TLSServer TLS服务器
type TLSServer struct {
    // 证书文件路径
    certFile string
    
    // 私钥文件路径
    keyFile string
    
    // HTTP处理器
    handler http.Handler
}

// NewTLSServer 创建TLS服务器
func NewTLSServer(certFile, keyFile string, handler http.Handler) *TLSServer {
    return &TLSServer{
        certFile: certFile,
        keyFile:  keyFile,
        handler:  handler,
    }
}

// Start 启动TLS服务器
func (ts *TLSServer) Start(addr string) error {
    server := &http.Server{
        Addr:    addr,
        Handler: ts.handler,
        // 配置TLS
        TLSConfig: &tls.Config{
            MinVersion: tls.VersionTLS12,
            CipherSuites: []uint16{
                tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
                tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
                tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
                tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
            },
        },
    }
    
    return server.ListenAndServeTLS(ts.certFile, ts.keyFile)
}

敏感数据加密

对于存储在数据库中的敏感数据,我们需要进行加密处理。

// DataEncryptor 数据加密器
type DataEncryptor struct {
    // 加密密钥
    key []byte
}

// NewDataEncryptor 创建数据加密器
func NewDataEncryptor(key string) *DataEncryptor {
    return &DataEncryptor{
        key: []byte(key),
    }
}

// Encrypt 加密数据
func (de *DataEncryptor) Encrypt(plaintext string) (string, error) {
    // 创建AES加密器
    block, err := aes.NewCipher(de.key)
    if err != nil {
        return "", fmt.Errorf("failed to create cipher: %w", err)
    }
    
    // 生成随机IV
    iv := make([]byte, aes.BlockSize)
    if _, err := io.ReadFull(rand.Reader, iv); err != nil {
        return "", fmt.Errorf("failed to generate IV: %w", err)
    }
    
    // 填充明文
    paddedPlaintext := pkcs7Pad([]byte(plaintext), aes.BlockSize)
    
    // 加密
    ciphertext := make([]byte, len(paddedPlaintext))
    mode := cipher.NewCBCEncrypter(block, iv)
    mode.CryptBlocks(ciphertext, paddedPlaintext)
    
    // 将IV和密文组合
    result := append(iv, ciphertext...)
    
    // Base64编码
    return base64.StdEncoding.EncodeToString(result), nil
}

// Decrypt 解密数据
func (de *DataEncryptor) Decrypt(ciphertext string) (string, error) {
    // Base64解码
    data, err := base64.StdEncoding.DecodeString(ciphertext)
    if err != nil {
        return "", fmt.Errorf("failed to decode base64: %w", err)
    }
    
    // 分离IV和密文
    if len(data) < aes.BlockSize {
        return "", fmt.Errorf("ciphertext too short")
    }
    
    iv := data[:aes.BlockSize]
    encrypted := data[aes.BlockSize:]
    
    // 创建AES解密器
    block, err := aes.NewCipher(de.key)
    if err != nil {
        return "", fmt.Errorf("failed to create cipher: %w", err)
    }
    
    // 解密
    mode := cipher.NewCBCDecrypter(block, iv)
    paddedPlaintext := make([]byte, len(encrypted))
    mode.CryptBlocks(paddedPlaintext, encrypted)
    
    // 去除填充
    plaintext, err := pkcs7Unpad(paddedPlaintext)
    if err != nil {
        return "", fmt.Errorf("failed to unpad: %w", err)
    }
    
    return string(plaintext), nil
}

// pkcs7Pad PKCS#7填充
func pkcs7Pad(data []byte, blockSize int) []byte {
    padding := blockSize - len(data)%blockSize
    padtext := bytes.Repeat([]byte{byte(padding)}, padding)
    return append(data, padtext...)
}

// pkcs7Unpad PKCS#7去除填充
func pkcs7Unpad(data []byte) ([]byte, error) {
    length := len(data)
    if length == 0 {
        return nil, fmt.Errorf("invalid padding size")
    }
    
    unpadding := int(data[length-1])
    if unpadding > length {
        return nil, fmt.Errorf("invalid padding size")
    }
    
    return data[:(length - unpadding)], nil
}

访问控制机制

IP白名单/黑名单

// IPAccessControl IP访问控制
type IPAccessControl struct {
    // 白名单
    whitelist map[string]bool
    
    // 黑名单
    blacklist map[string]bool
    
    // 互斥锁
    mutex sync.RWMutex
}

// NewIPAccessControl 创建IP访问控制
func NewIPAccessControl() *IPAccessControl {
    return &IPAccessControl{
        whitelist: make(map[string]bool),
        blacklist: make(map[string]bool),
    }
}

// AddToWhitelist 添加到白名单
func (iac *IPAccessControl) AddToWhitelist(ip string) {
    iac.mutex.Lock()
    defer iac.mutex.Unlock()
    
    iac.whitelist[ip] = true
}

// AddToBlacklist 添加到黑名单
func (iac *IPAccessControl) AddToBlacklist(ip string) {
    iac.mutex.Lock()
    defer iac.mutex.Unlock()
    
    iac.blacklist[ip] = true
}

// IsAllowed 检查IP是否被允许访问
func (iac *IPAccessControl) IsAllowed(ip string) bool {
    iac.mutex.RLock()
    defer iac.mutex.RUnlock()
    
    // 如果存在白名单,则只允许白名单中的IP访问
    if len(iac.whitelist) > 0 {
        return iac.whitelist[ip]
    }
    
    // 如果存在黑名单,则拒绝黑名单中的IP访问
    if len(iac.blacklist) > 0 {
        return !iac.blacklist[ip]
    }
    
    // 默认允许访问
    return true
}

安全审计机制

请求日志记录

// SecurityLogger 安全日志记录器
type SecurityLogger struct {
    // 日志文件
    logFile *os.File
    
    // 日志写入器
    logger *log.Logger
}

// SecurityLogEntry 安全日志条目
type SecurityLogEntry struct {
    // 时间戳
    Timestamp time.Time `json:"timestamp"`
    
    // 请求ID
    RequestID string `json:"request_id"`
    
    // 客户端IP
    ClientIP string `json:"client_ip"`
    
    // 用户ID
    UserID string `json:"user_id,omitempty"`
    
    // 请求方法
    Method string `json:"method"`
    
    // 请求路径
    Path string `json:"path"`
    
    // 请求参数
    Params map[string]interface{} `json:"params,omitempty"`
    
    // 响应状态码
    StatusCode int `json:"status_code"`
    
    // 响应时间
    ResponseTime time.Duration `json:"response_time"`
    
    // 用户代理
    UserAgent string `json:"user_agent,omitempty"`
    
    // 错误信息
    Error string `json:"error,omitempty"`
}

// NewSecurityLogger 创建安全日志记录器
func NewSecurityLogger(logFilePath string) (*SecurityLogger, error) {
    // 打开日志文件
    file, err := os.OpenFile(logFilePath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
    if err != nil {
        return nil, fmt.Errorf("failed to open log file: %w", err)
    }
    
    return &SecurityLogger{
        logFile: file,
        logger:  log.New(file, "", 0),
    }, nil
}

// Log 记录安全日志
func (sl *SecurityLogger) Log(entry *SecurityLogEntry) {
    // 序列化为JSON
    data, err := json.Marshal(entry)
    if err != nil {
        log.Printf("failed to marshal security log entry: %v", err)
        return
    }
    
    // 写入日志
    sl.logger.Println(string(data))
}

// Close 关闭日志记录器
func (sl *SecurityLogger) Close() error {
    return sl.logFile.Close()
}

使用示例

// 初始化安全组件
jwtAuth := NewJWTAuth("your-secret-key", 24*time.Hour)
oauth2Auth := NewOAuth2Auth(clientStore, tokenStore, &OAuth2Config{
    AccessTokenExpire:  1 * time.Hour,
    RefreshTokenExpire: 7 * 24 * time.Hour,
    AuthCodeExpire:     10 * time.Minute,
})
rbacAuth := NewRBACAuth(roleStore, userRoleStore, permissionStore)
dataEncryptor := NewDataEncryptor("your-encryption-key")
ipAccessControl := NewIPAccessControl()
securityLogger, _ := NewSecurityLogger("security.log")

// 添加IP白名单
ipAccessControl.AddToWhitelist("192.168.1.100")
ipAccessControl.AddToWhitelist("10.0.0.0/8")

// API安全中间件
func securityMiddleware(next http.HandlerFunc) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
        startTime := time.Now()
        requestID := generateRequestID()
        
        // 记录请求信息
        logEntry := &SecurityLogEntry{
            Timestamp: startTime,
            RequestID: requestID,
            ClientIP:  getClientIP(r),
            Method:    r.Method,
            Path:      r.URL.Path,
            UserAgent: r.UserAgent(),
        }
        
        // IP访问控制
        if !ipAccessControl.IsAllowed(getClientIP(r)) {
            logEntry.StatusCode = http.StatusForbidden
            logEntry.Error = "IP not allowed"
            logEntry.ResponseTime = time.Since(startTime)
            securityLogger.Log(logEntry)
            
            http.Error(w, "Forbidden", http.StatusForbidden)
            return
        }
        
        // JWT认证
        authHeader := r.Header.Get("Authorization")
        if authHeader == "" {
            logEntry.StatusCode = http.StatusUnauthorized
            logEntry.Error = "Missing authorization header"
            logEntry.ResponseTime = time.Since(startTime)
            securityLogger.Log(logEntry)
            
            http.Error(w, "Unauthorized", http.StatusUnauthorized)
            return
        }
        
        tokenString := strings.TrimPrefix(authHeader, "Bearer ")
        claims, err := jwtAuth.ValidateToken(tokenString)
        if err != nil {
            logEntry.StatusCode = http.StatusUnauthorized
            logEntry.Error = fmt.Sprintf("Invalid token: %v", err)
            logEntry.ResponseTime = time.Since(startTime)
            securityLogger.Log(logEntry)
            
            http.Error(w, "Unauthorized", http.StatusUnauthorized)
            return
        }
        
        logEntry.UserID = claims.BizID
        
        // RBAC权限检查
        allowed, err := rbacAuth.CheckPermission(claims.BizID, r.URL.Path, r.Method)
        if err != nil || !allowed {
            logEntry.StatusCode = http.StatusForbidden
            logEntry.Error = "Permission denied"
            logEntry.ResponseTime = time.Since(startTime)
            securityLogger.Log(logEntry)
            
            http.Error(w, "Forbidden", http.StatusForbidden)
            return
        }
        
        // 调用下一个处理器
        next.ServeHTTP(w, r)
        
        // 记录响应信息
        logEntry.StatusCode = http.StatusOK
        logEntry.ResponseTime = time.Since(startTime)
        securityLogger.Log(logEntry)
    }
}

// 加密敏感数据示例
func saveAPIToken(bizID, accessKeySecret string) error {
    // 加密密钥
    encryptedSecret, err := dataEncryptor.Encrypt(accessKeySecret)
    if err != nil {
        return fmt.Errorf("failed to encrypt secret: %w", err)
    }
    
    // 保存到数据库
    _, err = db.Exec("INSERT INTO api_tokens (biz_id, access_key_secret) VALUES (?, ?)", 
        bizID, encryptedSecret)
    if err != nil {
        return fmt.Errorf("failed to save token: %w", err)
    }
    
    return nil
}

// 解密敏感数据示例
func getAPIToken(bizID string) (string, error) {
    var encryptedSecret string
    err := db.QueryRow("SELECT access_key_secret FROM api_tokens WHERE biz_id = ?", bizID).Scan(&encryptedSecret)
    if err != nil {
        return "", fmt.Errorf("failed to get token: %w", err)
    }
    
    // 解密密钥
    secret, err := dataEncryptor.Decrypt(encryptedSecret)
    if err != nil {
        return "", fmt.Errorf("failed to decrypt secret: %w", err)
    }
    
    return secret, nil
}

总结

通过以上安全策略的设计和实现,我们能够构建一个安全可靠的API系统:

  1. 多层次认证:JWT和OAuth 2.0提供了灵活的认证机制
  2. 细粒度授权:RBAC模型实现了基于角色的权限控制
  3. 数据加密:HTTPS和敏感数据加密保护了数据安全
  4. 访问控制:IP白名单/黑名单限制了非法访问
  5. 安全审计:详细的日志记录便于安全事件追踪

在实际应用中,还需要考虑以下几点:

  1. 密钥管理:安全地存储和轮换密钥
  2. 安全更新:及时更新安全组件和依赖库
  3. 漏洞扫描:定期进行安全漏洞扫描
  4. 应急响应:建立安全事件应急响应机制

在下一节中,我们将探讨如何设计高可用架构,确保系统的稳定性和可靠性。