116 lines
4.7 KiB
Go
116 lines
4.7 KiB
Go
package middleware
|
|
|
|
import (
|
|
"github.com/gin-gonic/gin"
|
|
"strings"
|
|
)
|
|
|
|
// SecurityHeadersConfig chứa cấu hình cho các security headers
|
|
type SecurityHeadersConfig struct {
|
|
// Có nên thêm các security headers hay không
|
|
Enabled bool `yaml:"enabled"`
|
|
// Chính sách bảo mật nội dung (Content Security Policy)
|
|
ContentSecurityPolicy string `yaml:"content_security_policy"`
|
|
// Chính sách bảo mật truy cập tài nguyên (Cross-Origin)
|
|
CrossOriginResourcePolicy string `yaml:"cross_origin_resource_policy"`
|
|
// Chính sách tương tác giữa các site (Cross-Origin)
|
|
CrossOriginOpenerPolicy string `yaml:"cross_origin_opener_policy"`
|
|
// Chính sách nhúng tài nguyên (Cross-Origin)
|
|
CrossOriginEmbedderPolicy string `yaml:"cross_origin_embedder_policy"`
|
|
// Chính sách tham chiếu (Referrer-Policy)
|
|
ReferrerPolicy string `yaml:"referrer_policy"`
|
|
// Chính sách sử dụng các tính năng trình duyệt (Feature-Policy)
|
|
FeaturePolicy string `yaml:"feature_policy"`
|
|
// Chính sách bảo vệ clickjacking (X-Frame-Options)
|
|
FrameOptions string `yaml:"frame_options"`
|
|
// Chính sách bảo vệ XSS (X-XSS-Protection)
|
|
XSSProtection string `yaml:"xss_protection"`
|
|
// Chính sách MIME type sniffing (X-Content-Type-Options)
|
|
ContentTypeOptions string `yaml:"content_type_options"`
|
|
// Chính sách Strict-Transport-Security (HSTS)
|
|
StrictTransportSecurity string `yaml:"strict_transport_security"`
|
|
// Chính sách Permissions-Policy (thay thế cho Feature-Policy)
|
|
PermissionsPolicy string `yaml:"permissions_policy"`
|
|
}
|
|
|
|
// DefaultSecurityHeadersConfig trả về cấu hình mặc định cho security headers
|
|
func DefaultSecurityHeadersConfig() SecurityHeadersConfig {
|
|
return SecurityHeadersConfig{
|
|
Enabled: true,
|
|
ContentSecurityPolicy: "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; connect-src 'self'",
|
|
CrossOriginResourcePolicy: "same-origin",
|
|
CrossOriginOpenerPolicy: "same-origin",
|
|
CrossOriginEmbedderPolicy: "require-corp",
|
|
ReferrerPolicy: "no-referrer-when-downgrade",
|
|
FeaturePolicy: "geolocation 'none'; midi 'none'; notifications 'none'; push 'none'; sync-xhr 'none'; microphone 'none'; camera 'none'; magnetometer 'none'; gyroscope 'none'; speaker 'none'; vibrate 'none'; fullscreen 'none'; payment 'none'",
|
|
FrameOptions: "DENY",
|
|
XSSProtection: "1; mode=block",
|
|
ContentTypeOptions: "nosniff",
|
|
StrictTransportSecurity: "max-age=31536000; includeSubDomains; preload",
|
|
PermissionsPolicy: "geolocation=(), microphone=(), camera=()",
|
|
}
|
|
}
|
|
|
|
// SecurityHeadersMiddleware thêm các security headers vào response
|
|
func SecurityHeadersMiddleware(config SecurityHeadersConfig) gin.HandlerFunc {
|
|
if !config.Enabled {
|
|
// Nếu không bật, trả về middleware trống
|
|
return func(c *gin.Context) {
|
|
c.Next()
|
|
}
|
|
}
|
|
|
|
// Chuẩn hóa các giá trị cấu hình
|
|
if config.ContentSecurityPolicy == "" {
|
|
config.ContentSecurityPolicy = "default-src 'self'"
|
|
}
|
|
if config.FrameOptions == "" {
|
|
config.FrameOptions = "DENY"
|
|
}
|
|
if config.XSSProtection == "" {
|
|
config.XSSProtection = "1; mode=block"
|
|
}
|
|
if config.ContentTypeOptions == "" {
|
|
config.ContentTypeOptions = "nosniff"
|
|
}
|
|
|
|
return func(c *gin.Context) {
|
|
// Thêm các security headers
|
|
if config.ContentSecurityPolicy != "" {
|
|
c.Writer.Header().Set("Content-Security-Policy", config.ContentSecurityPolicy)
|
|
}
|
|
if config.CrossOriginResourcePolicy != "" {
|
|
c.Writer.Header().Set("Cross-Origin-Resource-Policy", config.CrossOriginResourcePolicy)
|
|
}
|
|
if config.CrossOriginOpenerPolicy != "" {
|
|
c.Writer.Header().Set("Cross-Origin-Opener-Policy", config.CrossOriginOpenerPolicy)
|
|
}
|
|
if config.CrossOriginEmbedderPolicy != "" {
|
|
c.Writer.Header().Set("Cross-Origin-Embedder-Policy", config.CrossOriginEmbedderPolicy)
|
|
}
|
|
if config.ReferrerPolicy != "" {
|
|
c.Writer.Header().Set("Referrer-Policy", config.ReferrerPolicy)
|
|
}
|
|
if config.FeaturePolicy != "" {
|
|
c.Writer.Header().Set("Feature-Policy", config.FeaturePolicy)
|
|
}
|
|
if config.FrameOptions != "" {
|
|
c.Writer.Header().Set("X-Frame-Options", config.FrameOptions)
|
|
}
|
|
if config.XSSProtection != "" {
|
|
c.Writer.Header().Set("X-XSS-Protection", config.XSSProtection)
|
|
}
|
|
if config.ContentTypeOptions != "" {
|
|
c.Writer.Header().Set("X-Content-Type-Options", config.ContentTypeOptions)
|
|
}
|
|
if config.StrictTransportSecurity != "" && strings.ToLower(c.Request.URL.Scheme) == "https" {
|
|
c.Writer.Header().Set("Strict-Transport-Security", config.StrictTransportSecurity)
|
|
}
|
|
if config.PermissionsPolicy != "" {
|
|
c.Writer.Header().Set("Permissions-Policy", config.PermissionsPolicy)
|
|
}
|
|
|
|
c.Next()
|
|
}
|
|
}
|