Ответ
На последнем проекте я разрабатывал микросервис управления пользователями (аутентификация, авторизация, профиль) на Go.
Стек технологий:
- Фреймворк: Echo
- База данных: PostgreSQL для хранения данных пользователей.
- Кэш: Redis для кэширования сессий и часто запрашиваемых данных.
Ключевые задачи, которые я решал:
- Реализация JWT-аутентификации: Разработал middleware для проверки JWT-токенов и ролевого доступа (RBAC). Токены содержали информацию о
userID
иrole
. - Оптимизация работы с БД: Использовал
pgx
с пулом соединений (connection pooling
) иprepared statements
для защиты от SQL-инъекций и ускорения выполнения повторяющихся запросов. - Написание тестов: Покрыл бизнес-логику юнит-тестами с помощью
testify/assert
и написал интеграционные тесты с использованиемdockertest
.dockertest
позволял поднимать временный инстанс PostgreSQL в Docker для каждого тестового прогона, обеспечивая полную изоляцию тестов.
Пример аутентификационного middleware для фреймворка Echo:
import (
"net/http"
"strings"
"github.com/golang-jwt/jwt/v4"
"github.com/labstack/echo/v4"
)
// Claims определяет структуру данных, хранимых в JWT
type Claims struct {
UserID int `json:"user_id"`
jwt.RegisteredClaims
}
var jwtSecret = []byte("your_secret_key")
// AuthMiddleware проверяет заголовок Authorization и валидирует JWT
func AuthMiddleware(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
authHeader := c.Request().Header.Get("Authorization")
if authHeader == "" {
return c.JSON(http.StatusUnauthorized, "missing authorization header")
}
// Токен обычно передается в формате "Bearer <token>"
tokenString := strings.TrimPrefix(authHeader, "Bearer ")
if tokenString == authHeader { // Префикс не найден
return c.JSON(http.StatusUnauthorized, "invalid token format")
}
claims := &Claims{}
token, err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (interface{}, error) {
return jwtSecret, nil
})
if err != nil || !token.Valid {
return c.JSON(http.StatusUnauthorized, "invalid token")
}
// Сохраняем ID пользователя в контексте запроса для дальнейшего использования
c.Set("userID", claims.UserID)
return next(c)
}
}
Проект велся по методологии Scrum с двухнедельными спринтами. Для CI/CD мы использовали GitLab CI, который автоматически собирал, тестировал и деплоил приложение в кластер Kubernetes.