mirror of
https://github.com/Direct-Dev-Ru/go-lcg.git
synced 2025-11-16 01:29:55 +00:00
115 lines
3.7 KiB
Go
115 lines
3.7 KiB
Go
package serve
|
||
|
||
import (
|
||
"net/http"
|
||
"strings"
|
||
|
||
"github.com/direct-dev-ru/linux-command-gpt/config"
|
||
)
|
||
|
||
// AuthMiddleware проверяет аутентификацию для всех запросов
|
||
func AuthMiddleware(next http.HandlerFunc) http.HandlerFunc {
|
||
return func(w http.ResponseWriter, r *http.Request) {
|
||
// Проверяем, требуется ли аутентификация
|
||
if !config.AppConfig.Server.RequireAuth {
|
||
next(w, r)
|
||
return
|
||
}
|
||
|
||
// Исключаем страницу входа и API логина из проверки (с учетом BasePath)
|
||
if r.URL.Path == makePath("/login") || r.URL.Path == makePath("/api/login") || r.URL.Path == makePath("/api/validate-token") {
|
||
next(w, r)
|
||
return
|
||
}
|
||
|
||
// Проверяем аутентификацию
|
||
if !isAuthenticated(r) {
|
||
// Для API запросов возвращаем JSON ошибку
|
||
if isAPIRequest(r) {
|
||
w.Header().Set("Content-Type", "application/json")
|
||
w.WriteHeader(http.StatusUnauthorized)
|
||
w.Write([]byte(`{"success": false, "error": "Authentication required"}`))
|
||
return
|
||
}
|
||
|
||
// Для веб-запросов перенаправляем на страницу входа (с учетом BasePath)
|
||
http.Redirect(w, r, makePath("/login"), http.StatusSeeOther)
|
||
return
|
||
}
|
||
|
||
// Пользователь аутентифицирован, продолжаем
|
||
next(w, r)
|
||
}
|
||
}
|
||
|
||
// CSRFMiddleware проверяет CSRF токены для POST/PUT/DELETE запросов
|
||
func CSRFMiddleware(next http.HandlerFunc) http.HandlerFunc {
|
||
return func(w http.ResponseWriter, r *http.Request) {
|
||
// Проверяем только изменяющие запросы
|
||
if r.Method == "GET" || r.Method == "HEAD" || r.Method == "OPTIONS" {
|
||
next(w, r)
|
||
return
|
||
}
|
||
|
||
// Исключаем некоторые API endpoints (с учетом BasePath)
|
||
if r.URL.Path == makePath("/api/login") || r.URL.Path == makePath("/api/logout") {
|
||
next(w, r)
|
||
return
|
||
}
|
||
|
||
// Получаем CSRF токен из заголовка или формы
|
||
csrfToken := r.Header.Get("X-CSRF-Token")
|
||
if csrfToken == "" {
|
||
csrfToken = r.FormValue("csrf_token")
|
||
}
|
||
|
||
if csrfToken == "" {
|
||
// Для API запросов возвращаем JSON ошибку
|
||
if isAPIRequest(r) {
|
||
w.Header().Set("Content-Type", "application/json")
|
||
w.WriteHeader(http.StatusForbidden)
|
||
w.Write([]byte(`{"success": false, "error": "CSRF token required"}`))
|
||
return
|
||
}
|
||
|
||
// Для веб-запросов возвращаем ошибку
|
||
http.Error(w, "CSRF token required", http.StatusForbidden)
|
||
return
|
||
}
|
||
|
||
// Получаем сессионный ID
|
||
sessionID := getSessionID(r)
|
||
|
||
// Проверяем CSRF токен
|
||
csrfManager := GetCSRFManager()
|
||
if csrfManager == nil || !csrfManager.ValidateToken(csrfToken, sessionID) {
|
||
// Для API запросов возвращаем JSON ошибку
|
||
if isAPIRequest(r) {
|
||
w.Header().Set("Content-Type", "application/json")
|
||
w.WriteHeader(http.StatusForbidden)
|
||
w.Write([]byte(`{"success": false, "error": "Invalid CSRF token"}`))
|
||
return
|
||
}
|
||
|
||
// Для веб-запросов возвращаем ошибку
|
||
http.Error(w, "Invalid CSRF token", http.StatusForbidden)
|
||
return
|
||
}
|
||
|
||
// CSRF токен валиден, продолжаем
|
||
next(w, r)
|
||
}
|
||
}
|
||
|
||
// isAPIRequest проверяет, является ли запрос API запросом
|
||
func isAPIRequest(r *http.Request) bool {
|
||
path := r.URL.Path
|
||
apiPrefix := makePath("/api")
|
||
return strings.HasPrefix(path, apiPrefix)
|
||
}
|
||
|
||
// RequireAuth обертка для requireAuth из auth.go
|
||
func RequireAuth(next http.HandlerFunc) http.HandlerFunc {
|
||
return requireAuth(next)
|
||
}
|