express安全处理之helmet中间件丨技术开发分享录

express安全处理之helmet中间件

{{ detail.nickname }}

转载 翻译 {{ formatTime(detail.create_time) }} 字数 {{ detail.content && detail.content.length }} 阅读 {{ detail.read_num }} {{ formatTag(v) }}

"使用nodejs express框架搭建网站应用,在处理安全问题的时候就离不开helmet中间件了,为什么这么讲呢?\n\n主要是因为helmet集成了各种HTTP头信息来帮助保护Express应用程序, 如:XSS攻击、CSP内容安全策略、dns保护、iframe同源限制等,省得开发一个个处理了。\n\n## 一、安装使用\n\n```cmd\n> npm install helmet --save\n```\n\n在app.js引入使用,如果不想特殊设置就使用默认即可\n\n```\nconst express = require(\"express\");\nconst helmet = require(\"helmet\");\n \nconst app = express();\n \napp.use(helmet());\n```\n\n> 如果使用的是Koa框架,安装[koa-helmet](https://github.com/venables/koa-helmet)即可\n\n## 二、方法介绍\n\nhelmet总共结合了11个小中间件\n\n```\napp.use(helmet());\n```\n\n等同于\n\n```\napp.use(helmet.contentSecurityPolicy());\napp.use(helmet.dnsPrefetchControl());\napp.use(helmet.expectCt());\napp.use(helmet.frameguard());\napp.use(helmet.hidePoweredBy());\napp.use(helmet.hsts());\napp.use(helmet.ieNoOpen());\napp.use(helmet.noSniff());\napp.use(helmet.permittedCrossDomainPolicies());\napp.use(helmet.referrerPolicy());\napp.use(helmet.xssFilter());\n```\n\n### 1、helmet(option)\n\noption键为包含方法的方法名,值为该方法的选项值,不过里加了一个true/false用来启用/禁用该功能\n\n```\napp.use(\n  helmet({\n    frameguard: {\n      action: 'sameorigin' // iframe设置同源\n    },\n    contentSecurityPolicy: false, // 关闭内容安全策略\n    expectCt: { \n      maxAge: 86400 // 证书透明化最大时间为1天,单位秒\n    }\n  })\n);\n```\n\n### 2、helmet.contentSecurityPolicy(options)\n\n[CSP](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP)(Content Security Policy)内容安全策略\n\n主要用来预防跨站脚本攻击,不过这个中间件很少执行验证,完全依赖CSP设置\n\n- `options.directives`是一个对象,键为规则为`defaultSrc`或`default-src`。\n- `options.reportOnly`只读,是一个boolean值,默认为false\n\n如果没有提供指令,则设置以下策略:\n\n```text\ndefault-src 'self';\nbase-uri 'self';\nblock-all-mixed-content;\nfont-src 'self' https: data:;\nframe-ancestors 'self';\nimg-src 'self' data:;\nobject-src 'none';\nscript-src 'self';\nscript-src-attr 'none';\nstyle-src 'self' https: 'unsafe-inline';\nupgrade-insecure-requests\n```\n\n示例:\n\n```\n// Sets \"Content-Security-Policy: default-src 'self';script-src 'self' example.com;object-src 'none';upgrade-insecure-requests\"\napp.use(\n  helmet.contentSecurityPolicy({\n    directives: {\n      defaultSrc: [\"'self'\"],\n      scriptSrc: [\"'self'\", \"example.com\"],\n      objectSrc: [\"'none'\"],\n      upgradeInsecureRequests: [],\n    },\n  })\n);\n \n// Sets \"Content-Security-Policy: default-src 'self';script-src 'self' example.com;object-src 'none'\"\napp.use(\n  helmet.contentSecurityPolicy({\n    directives: {\n      \"default-src\": [\"'self'\"],\n      \"script-src\": [\"'self'\", \"example.com\"],\n      \"object-src\": [\"'none'\"],\n    },\n  })\n);\n \n// Sets the \"Content-Security-Policy-Report-Only\" header instead\napp.use(\n  helmet.contentSecurityPolicy({\n    directives: {\n      /* ... */\n    },\n    reportOnly: true,\n  })\n);\n \n// Sets \"Content-Security-Policy: default-src 'self';script-src 'self' 'nonce-e33ccde670f149c1789b1e1e113b0916'\"\napp.use((req, res, next) => {\n  res.locals.cspNonce = crypto.randomBytes(16).toString(\"hex\");\n  next();\n});\napp.use(\n  helmet.contentSecurityPolicy({\n    directives: {\n      defaultSrc: [\"'self'\"],\n      scriptSrc: [\"'self'\", (req, res) => `'nonce-${res.locals.cspNonce}'`],\n    },\n  })\n);\n```\n\n可以单独安装`helmet-csp`\n\n## 3、helmet.expectCt(options)\n\n`helmet.expectCt`设置了`Expect-CT`头,有助于减轻错误颁发的SSL证书,更多信息请参考MDN上的[Expect-CT](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Expect-CT)介绍\n\n- `options.maxAge`期望证书透明化的秒数,默认为0\n- `options.enforce`是一个布尔值。如果为true,用户代理(通常是浏览器)应该拒绝违反其证书透明策略的连接。默认值为false\n- `options.reportUri`是一个字符串,如果失败则向该URI报告\n\n示例:\n\n```\n// Sets \"Expect-CT: max-age=86400\"\napp.use(\n  helmet.expectCt({\n    maxAge: 86400,\n  })\n);\n \n// Sets \"Expect-CT: max-age=86400, enforce, report-uri=\"https://example.com/report\"\napp.use(\n  helmet.expectCt({\n    maxAge: 86400,\n    enforce: true,\n    reportUri: \"https://example.com/report\",\n  })\n);\n```\n\n可以单独安装`expect-ct`\n\n### 4、helmet.referrerPolicy(options)\n\n`helmet.referrerPolicy`设置`Referrer-Policy`头,更多信息请参考:[Referer](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referer)\n\n- `options.policy`字符串/数组,默认为no-referrer\n\n示例:\n\n```\n// Sets \"Referrer-Policy: no-referrer\"\napp.use(\n  helmet.referrerPolicy({\n    policy: \"no-referrer\",\n  })\n);\n \n// Sets \"Referrer-Policy: origin,unsafe-url\"\napp.use(\n  helmet.referrerPolicy({\n    policy: [\"origin\", \"unsafe-url\"],\n  })\n);\n```\n\n可以单独安装`referrer-policy`\n\n### 5、helmet.hsts(options)\n\n`helmet.hsts`设置[Strict-Transport-Security](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security)头,告诉浏览器使用安全的https协议而不是http\n\n- `options.maxAge`浏览器应该记住使用HTTPS的秒数。如果传递的是非整数,则该值四舍五入。它的默认值是15552000,也就是180天。\n- `options.includeSubDomains`是一个布尔值,指定是否包含includeSubDomains指令,该指令使此策略扩展到子域。它默认为true。\n- `options.preload`是一个布尔值。如果为真,它会添加preload指令,表示将HSTS策略添加到浏览器。更多信息请参考[Preloading Strict Transport Security](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security#Preloading_Strict_Transport_Security)。默认为false。\n\n示例:\n\n```\n// Sets \"Strict-Transport-Security: max-age=123456; includeSubDomains\"\napp.use(\n  helmet.strictTransportSecurity({\n    maxAge: 123456,\n  })\n);\n \n// Sets \"Strict-Transport-Security: max-age=123456\"\napp.use(\n  helmet.strictTransportSecurity({\n    maxAge: 123456,\n    includeSubDomains: false,\n  })\n);\n \n// Sets \"Strict-Transport-Security: max-age=123456; includeSubDomains; preload\"\napp.use(\n  helmet.strictTransportSecurity({\n    maxAge: 63072000,\n    preload: true,\n  })\n);\n```\n\n可以单独安装`hsts`\n\n### 6、helmet.noSniff()\n\n`helmet.noSniff`设置`X-Content-Type-Options`头为`nosniff`,这减轻了`MIME type sniffing`可能导致安全漏洞的影响。\n\n示例:\n\n```\n// Sets \"X-Content-Type-Options: nosniff\"\napp.use(helmet.noSniff());\n```\n\n可以单独安装`dont-sniff-mimetype`\n\n### 7、helmet.dnsPrefetchControl(options)\n\n`helmet.dnsPrefetchControl`设置`X-DNS-Prefetch-Control`头帮助控制DNS预取,这会以牺牲性能为代价提高用户隐私。\n更多信息请参考:[X-DNS-Prefetch-Control](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-DNS-Prefetch-Control)\n\n- `options.allow`是一个布尔值,指定是否启用DNS预取。默认为false。\n\n示例:\n\n```\n// Sets \"X-DNS-Prefetch-Control: off\"\napp.use(\n  helmet.dnsPrefetchControl({\n    allow: false,\n  })\n);\n \n// Sets \"X-DNS-Prefetch-Control: on\"\napp.use(\n  helmet.dnsPrefetchControl({\n    allow: true,\n  })\n);\n```\n\n可以单独安装`dns-prefetch-control`\n\n### 8、helmet.ieNoOpen()\n\n`helmet.ieNoOpen`设置`X-Download-Options`头,这是Internet Explorer 8特有的。强制保存潜在不安全的下载,减少了HTML在站点上下文中的执行。更多信息请参考:[IE8 Security](https://docs.microsoft.com/en-us/archive/blogs/ie/ie8-security-part-v-comprehensive-protection)\n\n示例:\n\n```\n// Sets \"X-Download-Options: noopen\"\napp.use(helmet.ieNoOpen());\n```\n\n可以单独安装`ienoopen`\n\n### 9、helmet.frameguard(options)\n\n`helmet.frameguard`设置`X-Frame-Options`头来预防点击劫持,这个功能被CSP的[frame-ancestors](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/frame-ancestors)替代了,不过对旧的浏览器仍然有用。更多信息请参考:[X-Frame-Options](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options)\n\n- `options.action`是一个字符串,指定使用哪个安全策略(`DENY`或`SAMEORIGIN`)不支持`ALLOW-FROM`,默认是`SAMEORIGIN`\n\n示例:\n\n```\n// Sets \"X-Frame-Options: DENY\"\napp.use(\n  helmet.frameguard({\n    action: \"deny\",\n  })\n);\n \n// Sets \"X-Frame-Options: SAMEORIGIN\"\napp.use(\n  helmet.frameguard({\n    action: \"sameorigin\",\n  })\n);\n```\n\n可以单独安装`frameguard`\n\n### 10、helmet.permittedCrossDomainPolicies(options)\n\n`helmet.permittedCrossDomainPolicies`设置`X-Permitted-Cross-Domain-Policies`头,告诉一些客户端(主要是Adobe产品)加载跨域内容策略。\n\n- `options.permittedPolicies`是一个字符串,值有:`none`、`master-only`、`by-content-type`和`all`,默认为`none`\n\n示例:\n\n```\n// Sets \"X-Permitted-Cross-Domain-Policies: none\"\napp.use(\n  helmet.permittedCrossDomainPolicies({\n    permittedPolicies: \"none\",\n  })\n);\n \n// Sets \"X-Permitted-Cross-Domain-Policies: by-content-type\"\napp.use(\n  helmet.permittedCrossDomainPolicies({\n    permittedPolicies: \"by-content-type\",\n  })\n);\n```\n\n可以单独安装`helmet-crossdomain`\n\n### 11、helmet.hidePoweredBy(options)\n\n`helmet.hidePoweredBy`删除`X-Powered-By`头,这在`Express`框架是默认设置的,安全作用有限,主要是为了节省带宽。\n\n示例:\n\n```\n// Removes the X-Powered-By header if it was set.\napp.use(helmet.hidePoweredBy());\n```\n\nExpress框架内置使用\n\n```\napp.disable(\"x-powered-by\");\n```\n\n可以单独安装`hide-powered-by`\n\n### 12、helmet.xssFilter(options)\n\n`helmet.xssFilter`设置`X-XSS-Protection`头为0来禁用浏览器的错误`XSS`过滤,更多信息请参考:[X-XSS-Protection](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-XSS-Protection)\n\n示例:\n\n```\n// Sets \"X-XSS-Protection: 0\"\napp.use(helmet.xssFilter());\n```\n\n可以单独安装`x-xss-protection`\n\n以上是关于helmet的总体介绍,在处理常规安全上基本都覆盖了,帮助开发者省了不少工作量。\n\n参考链接:\n\n- https://www.npmjs.com/package/helmet\n\n"
PS:写作不易,如要转裁,请标明转载出处。

如果此篇对您有帮助,可小额赞助,以兹鼓励!

猜你想看