Ответ
На последнем проекте я разрабатывал микросервис управления пользователями (аутентификация, авторизация, профиль) на 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.
Ответ 18+ 🔞
А, слушай, вот на прошлом проекте я вкалывал над микросервисом для пользователей — ну там, чтобы они логинились, права какие-то имели, профили меняли. Всё на Go, естественно.
Чем пользовался, блядь:
- Фреймворк: Echo, простой и быстрый, хуй с ним.
- База: PostgreSQL, куда ж без неё, там все данные юзеров лежали.
- Кэш: Redis, чтобы сессии и прочую часто запрашиваемую хуйню не гонять в основную базу каждый раз.
Что делал, ёпта:
- JWT-аутентификацию прикручивал: Написал middleware, который эти токены проверяет и смотрит, кто куда может лезть (RBAC, блядь). В токене у нас был
userIDиrole. - Базу оптимизировал: Использовал
pgxс пулом соединений иprepared statements— чтобы от SQL-инъекций защититься и чтобы одинаковые запросы быстрее летали, а не парсились каждый раз, как последние распиздяи. - Тесты писал, блядь: Бизнес-логику покрыл юнит-тестами на
testify/assert. А для интеграционных поднимал временную PostgreSQL в Docker черезdockertest— чтобы каждый тестовый прогон был в полной изоляции, как монах в келье. Красота, хуле.
Вот, например, как выглядел 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. Вроде мелочь, а приятно, когда не нужно вручную, как обезьяна, всё это делать.