Appearance
安全标头中间件
🌐 Secure Headers Middleware
安全头中间件简化了安全头的设置。部分受 Helmet 功能的启发,它允许你控制特定安全头的启用和禁用。
🌐 Secure Headers Middleware simplifies the setup of security headers. Inspired in part by the capabilities of Helmet, it allows you to control the activation and deactivation of specific security headers.
导入
🌐 Import
ts
import { Hono } from 'hono'
import { secureHeaders } from 'hono/secure-headers'用法
🌐 Usage
你可以默认使用最佳设置。
🌐 You can use the optimal settings by default.
ts
const app = new Hono()
app.use(secureHeaders())你可以通过将不必要的标头设置为 false 来抑制它们。
🌐 You can suppress unnecessary headers by setting them to false.
ts
const app = new Hono()
app.use(
'*',
secureHeaders({
xFrameOptions: false,
xXssProtection: false,
})
)你可以使用字符串覆盖默认标头值。
🌐 You can override default header values using a string.
ts
const app = new Hono()
app.use(
'*',
secureHeaders({
strictTransportSecurity:
'max-age=63072000; includeSubDomains; preload',
xFrameOptions: 'DENY',
xXssProtection: '1',
})
)支持的选项
🌐 Supported Options
每个选项对应以下 Header 键值对。
🌐 Each option corresponds to the following Header Key-Value pairs.
| 选项 | 头部 | 值 | 默认 |
|---|---|---|---|
| - | X-Powered-By | (删除头部信息) | 真 |
| contentSecurityPolicy | 内容安全策略 | 使用方法: 设置内容安全策略 | 未设置 |
| contentSecurityPolicyReportOnly | 内容安全策略仅报告 | 用法: 设置内容安全策略 | 未设置 |
| trustedTypes | 受信任的类型 | 用法: 设置内容安全策略 | 无设置 |
| requireTrustedTypesFor | 要求受信任类型 | 用法: 设置内容安全策略 | 无设置 |
| crossOriginEmbedderPolicy | 跨源嵌入策略 | require-corp | False |
| crossOriginResourcePolicy | 跨源资源策略 | same-origin | True |
| crossOriginOpenerPolicy | 跨源开启者策略 | same-origin | True |
| originAgentCluster | Origin-Agent-Cluster | ?1 | True |
| referrerPolicy | Referrer-Policy | no-referrer | True |
| reportingEndpoints | 报告端点 | 用法: 设置内容安全策略 | 无设置 |
| reportTo | Report-To | 用法: 设置内容安全策略 | 未设置 |
| strictTransportSecurity | 严格传输安全 | max-age=15552000; includeSubDomains | True |
| xContentTypeOptions | X-Content-Type-Options | nosniff | True |
| xDnsPrefetchControl | X-DNS-Prefetch-Control | 关闭 | 真 |
| xDownloadOptions | X-Download-Options | noopen | True |
| xFrameOptions | X-Frame-Options | SAMEORIGIN | True |
| xPermittedCrossDomainPolicies | X-Permitted-Cross-Domain-Policies | 无 | 真 |
| xXssProtection | X-XSS-Protection | 0 | 真 |
| permissionPolicy | 权限策略 | 用法: 设置权限策略 | 无设置 |
中间件冲突
🌐 Middleware Conflict
处理操纵相同标头的中间件时,请谨慎规范的顺序。
🌐 Please be cautious about the order of specification when dealing with middleware that manipulates the same header.
在这种情况下,Secure-headers 会运行,并且 x-powered-by 被移除:
🌐 In this case, Secure-headers operates and the x-powered-by is removed:
ts
const app = new Hono()
app.use(secureHeaders())
app.use(poweredBy())在这种情况下,Powered-By 会运行,并且添加 x-powered-by:
🌐 In this case, Powered-By operates and the x-powered-by is added:
ts
const app = new Hono()
app.use(poweredBy())
app.use(secureHeaders())设置内容安全策略
🌐 Setting Content-Security-Policy
ts
const app = new Hono()
app.use(
'/test',
secureHeaders({
reportingEndpoints: [
{
name: 'endpoint-1',
url: 'https://example.com/reports',
},
],
// -- or alternatively
// reportTo: [
// {
// group: 'endpoint-1',
// max_age: 10886400,
// endpoints: [{ url: 'https://example.com/reports' }],
// },
// ],
contentSecurityPolicy: {
defaultSrc: ["'self'"],
baseUri: ["'self'"],
childSrc: ["'self'"],
connectSrc: ["'self'"],
fontSrc: ["'self'", 'https:', 'data:'],
formAction: ["'self'"],
frameAncestors: ["'self'"],
frameSrc: ["'self'"],
imgSrc: ["'self'", 'data:'],
manifestSrc: ["'self'"],
mediaSrc: ["'self'"],
objectSrc: ["'none'"],
reportTo: 'endpoint-1',
reportUri: '/csp-report',
sandbox: ['allow-same-origin', 'allow-scripts'],
scriptSrc: ["'self'"],
scriptSrcAttr: ["'none'"],
scriptSrcElem: ["'self'"],
styleSrc: ["'self'", 'https:', "'unsafe-inline'"],
styleSrcAttr: ['none'],
styleSrcElem: ["'self'", 'https:', "'unsafe-inline'"],
upgradeInsecureRequests: [],
workerSrc: ["'self'"],
},
})
)nonce 属性
🌐 nonce attribute
你可以通过将从 hono/secure-headers 导入的 NONCE 添加到 scriptSrc 或 styleSrc 来为 script 或 style 元素添加 nonce 属性:
🌐 You can add a nonce attribute to a script or style element by adding the NONCE imported from hono/secure-headers to a scriptSrc or styleSrc:
tsx
import { secureHeaders, NONCE } from 'hono/secure-headers'
import type { SecureHeadersVariables } from 'hono/secure-headers'
// Specify the variable types to infer the `c.get('secureHeadersNonce')`:
type Variables = SecureHeadersVariables
const app = new Hono<{ Variables: Variables }>()
// Set the pre-defined nonce value to `scriptSrc`:
app.get(
'*',
secureHeaders({
contentSecurityPolicy: {
scriptSrc: [NONCE, 'https://allowed1.example.com'],
},
})
)
// Get the value from `c.get('secureHeadersNonce')`:
app.get('/', (c) => {
return c.html(
<html>
<body>
{/** contents */}
<script
src='/js/client.js'
nonce={c.get('secureHeadersNonce')}
/>
</body>
</html>
)
})如果你想要自己生成 nonce 值,也可以像下面这样指定一个函数:
🌐 If you want to generate the nonce value yourself, you can also specify a function as the following:
tsx
const app = new Hono<{
Variables: { myNonce: string }
}>()
const myNonceGenerator: ContentSecurityPolicyOptionHandler = (c) => {
// This function is called on every request.
const nonce = Math.random().toString(36).slice(2)
c.set('myNonce', nonce)
return `'nonce-${nonce}'`
}
app.get(
'*',
secureHeaders({
contentSecurityPolicy: {
scriptSrc: [myNonceGenerator, 'https://allowed1.example.com'],
},
})
)
app.get('/', (c) => {
return c.html(
<html>
<body>
{/** contents */}
<script src='/js/client.js' nonce={c.get('myNonce')} />
</body>
</html>
)
})设置权限策略
🌐 Setting Permission-Policy
Permission-Policy 头允许你控制浏览器中可以使用的功能和 API。以下是设置它的示例:
🌐 The Permission-Policy header allows you to control which features and APIs can be used in the browser. Here's an example of how to set it:
ts
const app = new Hono()
app.use(
'*',
secureHeaders({
permissionsPolicy: {
fullscreen: ['self'], // fullscreen=(self)
bluetooth: ['none'], // bluetooth=(none)
payment: ['self', 'https://example.com'], // payment=(self "https://example.com")
syncXhr: [], // sync-xhr=()
camera: false, // camera=none
microphone: true, // microphone=*
geolocation: ['*'], // geolocation=*
usb: ['self', 'https://a.example.com', 'https://b.example.com'], // usb=(self "https://a.example.com" "https://b.example.com")
accelerometer: ['https://*.example.com'], // accelerometer=("https://*.example.com")
gyroscope: ['src'], // gyroscope=(src)
magnetometer: [
'https://a.example.com',
'https://b.example.com',
], // magnetometer=("https://a.example.com" "https://b.example.com")
},
})
)