Ответ
Безопасность API — это многоуровневый процесс. Основные подходы включают:
Шифрование канала связи (TLS/HTTPS): Обязательное использование HTTPS для шифрования всего трафика между клиентом и сервером, что предотвращает перехват и изменение данных (атаки Man-in-the-Middle).
Аутентификация (Кто ты?): Проверка личности клиента. Популярные методы:
- JWT (JSON Web Tokens): Клиент получает токен после входа в систему и прикрепляет его к каждому последующему запросу. Сервер валидирует токен.
- OAuth 2.0: Стандарт для делегирования доступа. Позволяет приложениям получать доступ к ресурсам от имени пользователя, не зная его пароля.
Авторизация (Что тебе можно?): Определение прав доступа аутентифицированного пользователя. Распространенные модели:
- RBAC (Role-Based Access Control): Доступ определяется ролями (например,
admin
,user
,guest
). - ABAC (Attribute-Based Access Control): Более гибкая модель, где доступ зависит от атрибутов пользователя, ресурса и окружения.
- RBAC (Role-Based Access Control): Доступ определяется ролями (например,
Валидация входных данных: Никогда не доверяйте данным от клиента. Проверяйте все параметры, заголовки и тело запроса на соответствие формату, типу и бизнес-логике. Используйте библиотеки, такие как
go-playground/validator
.Ограничение частоты запросов (Rate Limiting): Защита от DoS-атак и злоупотреблений путем ограничения количества запросов от одного IP-адреса или пользователя за определенный период времени.
Пример JWT Middleware в Go с передачей данных через контекст:
// AuthMiddleware проверяет JWT и передает ID пользователя в контекст запроса.
func AuthMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Секретный ключ должен храниться в переменных окружения, а не в коде!
jwtSecret := os.Getenv("JWT_SECRET_KEY")
authHeader := r.Header.Get("Authorization")
if authHeader == "" {
http.Error(w, "Missing authorization header", http.StatusUnauthorized)
return
}
// Токен обычно передается в формате "Bearer <token>"
tokenString := strings.TrimPrefix(authHeader, "Bearer ")
token, err := jwt.Parse(tokenString, 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 []byte(jwtSecret), nil
})
if err != nil || !token.Valid {
http.Error(w, "Unauthorized", http.StatusUnauthorized)
return
}
// Извлекаем claims и передаем ID пользователя в следующий обработчик
if claims, ok := token.Claims.(jwt.MapClaims); ok {
userID := claims["user_id"].(string) // или другой тип
ctx := context.WithValue(r.Context(), "userID", userID)
next.ServeHTTP(w, r.WithContext(ctx))
} else {
http.Error(w, "Unauthorized", http.StatusUnauthorized)
}
})
}
Дополнительные меры:
- CORS (Cross-Origin Resource Sharing): Настройте политики для контроля доступа к API из браузеров с других доменов.
- Логирование и мониторинг: Ведите подробные логи всех запросов и настройте алерты на подозрительную активность.
- Безопасность зависимостей: Регулярно сканируйте и обновляйте зависимости проекта для защиты от известных уязвимостей.