feat: backend core - auth, user, role, permission, device, webhook, monitoring, cache, repository, service, middleware, API handlers
This commit is contained in:
45
internal/api/middleware/security_headers.go
Normal file
45
internal/api/middleware/security_headers.go
Normal file
@@ -0,0 +1,45 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
const contentSecurityPolicy = "default-src 'none'; frame-ancestors 'none'; base-uri 'none'; form-action 'self'"
|
||||
|
||||
func SecurityHeaders() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
headers := c.Writer.Header()
|
||||
headers.Set("X-Content-Type-Options", "nosniff")
|
||||
headers.Set("X-Frame-Options", "DENY")
|
||||
headers.Set("Referrer-Policy", "strict-origin-when-cross-origin")
|
||||
headers.Set("Permissions-Policy", "camera=(), microphone=(), geolocation=()")
|
||||
headers.Set("Cross-Origin-Opener-Policy", "same-origin")
|
||||
headers.Set("X-Permitted-Cross-Domain-Policies", "none")
|
||||
|
||||
if shouldAttachCSP(c.FullPath(), c.Request.URL.Path) {
|
||||
headers.Set("Content-Security-Policy", contentSecurityPolicy)
|
||||
}
|
||||
if isHTTPSRequest(c) {
|
||||
headers.Set("Strict-Transport-Security", "max-age=31536000; includeSubDomains")
|
||||
}
|
||||
|
||||
c.Next()
|
||||
}
|
||||
}
|
||||
|
||||
func shouldAttachCSP(routePath, requestPath string) bool {
|
||||
path := strings.TrimSpace(routePath)
|
||||
if path == "" {
|
||||
path = strings.TrimSpace(requestPath)
|
||||
}
|
||||
return !strings.HasPrefix(path, "/swagger/")
|
||||
}
|
||||
|
||||
func isHTTPSRequest(c *gin.Context) bool {
|
||||
if c.Request.TLS != nil {
|
||||
return true
|
||||
}
|
||||
return strings.EqualFold(strings.TrimSpace(c.GetHeader("X-Forwarded-Proto")), "https")
|
||||
}
|
||||
Reference in New Issue
Block a user