security.go 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
  1. package middleware
  2. import (
  3. "net/http"
  4. "github.com/mhsanaei/3x-ui/v3/web/session"
  5. "github.com/gin-gonic/gin"
  6. )
  7. // SecurityHeadersMiddleware adds browser hardening headers to panel responses.
  8. func SecurityHeadersMiddleware(directHTTPS bool) gin.HandlerFunc {
  9. return func(c *gin.Context) {
  10. c.Header("X-Content-Type-Options", "nosniff")
  11. c.Header("X-Frame-Options", "DENY")
  12. c.Header("Referrer-Policy", "no-referrer")
  13. c.Header("Content-Security-Policy", "frame-ancestors 'none'; base-uri 'self'; form-action 'self'")
  14. if directHTTPS {
  15. c.Header("Strict-Transport-Security", "max-age=31536000; includeSubDomains")
  16. }
  17. c.Next()
  18. }
  19. }
  20. // CSRFMiddleware rejects unsafe requests that do not include the session CSRF token.
  21. // Bearer-token-authenticated callers (api_authed flag set by APIController.checkAPIAuth)
  22. // short-circuit the CSRF check — they are not browser sessions, so the
  23. // cross-site request forgery threat model doesn't apply to them.
  24. func CSRFMiddleware() gin.HandlerFunc {
  25. return func(c *gin.Context) {
  26. if c.GetBool("api_authed") {
  27. c.Next()
  28. return
  29. }
  30. if isSafeMethod(c.Request.Method) {
  31. c.Next()
  32. return
  33. }
  34. if !session.ValidateCSRFToken(c) {
  35. c.AbortWithStatus(http.StatusForbidden)
  36. return
  37. }
  38. c.Next()
  39. }
  40. }
  41. func isSafeMethod(method string) bool {
  42. switch method {
  43. case http.MethodGet, http.MethodHead, http.MethodOptions, http.MethodTrace:
  44. return true
  45. default:
  46. return false
  47. }
  48. }