secure.go 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. package middleware
  2. import (
  3. "fmt"
  4. "github.com/labstack/echo"
  5. )
  6. type (
  7. // SecureConfig defines the config for Secure middleware.
  8. SecureConfig struct {
  9. // Skipper defines a function to skip middleware.
  10. Skipper Skipper
  11. // XSSProtection provides protection against cross-site scripting attack (XSS)
  12. // by setting the `X-XSS-Protection` header.
  13. // Optional. Default value "1; mode=block".
  14. XSSProtection string `yaml:"xss_protection"`
  15. // ContentTypeNosniff provides protection against overriding Content-Type
  16. // header by setting the `X-Content-Type-Options` header.
  17. // Optional. Default value "nosniff".
  18. ContentTypeNosniff string `yaml:"content_type_nosniff"`
  19. // XFrameOptions can be used to indicate whether or not a browser should
  20. // be allowed to render a page in a <frame>, <iframe> or <object> .
  21. // Sites can use this to avoid clickjacking attacks, by ensuring that their
  22. // content is not embedded into other sites.provides protection against
  23. // clickjacking.
  24. // Optional. Default value "SAMEORIGIN".
  25. // Possible values:
  26. // - "SAMEORIGIN" - The page can only be displayed in a frame on the same origin as the page itself.
  27. // - "DENY" - The page cannot be displayed in a frame, regardless of the site attempting to do so.
  28. // - "ALLOW-FROM uri" - The page can only be displayed in a frame on the specified origin.
  29. XFrameOptions string `yaml:"x_frame_options"`
  30. // HSTSMaxAge sets the `Strict-Transport-Security` header to indicate how
  31. // long (in seconds) browsers should remember that this site is only to
  32. // be accessed using HTTPS. This reduces your exposure to some SSL-stripping
  33. // man-in-the-middle (MITM) attacks.
  34. // Optional. Default value 0.
  35. HSTSMaxAge int `yaml:"hsts_max_age"`
  36. // HSTSExcludeSubdomains won't include subdomains tag in the `Strict Transport Security`
  37. // header, excluding all subdomains from security policy. It has no effect
  38. // unless HSTSMaxAge is set to a non-zero value.
  39. // Optional. Default value false.
  40. HSTSExcludeSubdomains bool `yaml:"hsts_exclude_subdomains"`
  41. // ContentSecurityPolicy sets the `Content-Security-Policy` header providing
  42. // security against cross-site scripting (XSS), clickjacking and other code
  43. // injection attacks resulting from execution of malicious content in the
  44. // trusted web page context.
  45. // Optional. Default value "".
  46. ContentSecurityPolicy string `yaml:"content_security_policy"`
  47. }
  48. )
  49. var (
  50. // DefaultSecureConfig is the default Secure middleware config.
  51. DefaultSecureConfig = SecureConfig{
  52. Skipper: DefaultSkipper,
  53. XSSProtection: "1; mode=block",
  54. ContentTypeNosniff: "nosniff",
  55. XFrameOptions: "SAMEORIGIN",
  56. }
  57. )
  58. // Secure returns a Secure middleware.
  59. // Secure middleware provides protection against cross-site scripting (XSS) attack,
  60. // content type sniffing, clickjacking, insecure connection and other code injection
  61. // attacks.
  62. func Secure() echo.MiddlewareFunc {
  63. return SecureWithConfig(DefaultSecureConfig)
  64. }
  65. // SecureWithConfig returns a Secure middleware with config.
  66. // See: `Secure()`.
  67. func SecureWithConfig(config SecureConfig) echo.MiddlewareFunc {
  68. // Defaults
  69. if config.Skipper == nil {
  70. config.Skipper = DefaultSecureConfig.Skipper
  71. }
  72. return func(next echo.HandlerFunc) echo.HandlerFunc {
  73. return func(c echo.Context) error {
  74. if config.Skipper(c) {
  75. return next(c)
  76. }
  77. req := c.Request()
  78. res := c.Response()
  79. if config.XSSProtection != "" {
  80. res.Header().Set(echo.HeaderXXSSProtection, config.XSSProtection)
  81. }
  82. if config.ContentTypeNosniff != "" {
  83. res.Header().Set(echo.HeaderXContentTypeOptions, config.ContentTypeNosniff)
  84. }
  85. if config.XFrameOptions != "" {
  86. res.Header().Set(echo.HeaderXFrameOptions, config.XFrameOptions)
  87. }
  88. if (c.IsTLS() || (req.Header.Get(echo.HeaderXForwardedProto) == "https")) && config.HSTSMaxAge != 0 {
  89. subdomains := ""
  90. if !config.HSTSExcludeSubdomains {
  91. subdomains = "; includeSubdomains"
  92. }
  93. res.Header().Set(echo.HeaderStrictTransportSecurity, fmt.Sprintf("max-age=%d%s", config.HSTSMaxAge, subdomains))
  94. }
  95. if config.ContentSecurityPolicy != "" {
  96. res.Header().Set(echo.HeaderContentSecurityPolicy, config.ContentSecurityPolicy)
  97. }
  98. return next(c)
  99. }
  100. }
  101. }