Skip to content

安全标头中间件

🌐 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-corpFalse
crossOriginResourcePolicy跨源资源策略same-originTrue
crossOriginOpenerPolicy跨源开启者策略same-originTrue
originAgentClusterOrigin-Agent-Cluster?1True
referrerPolicyReferrer-Policyno-referrerTrue
reportingEndpoints报告端点用法: 设置内容安全策略无设置
reportToReport-To用法: 设置内容安全策略未设置
strictTransportSecurity严格传输安全max-age=15552000; includeSubDomainsTrue
xContentTypeOptionsX-Content-Type-OptionsnosniffTrue
xDnsPrefetchControlX-DNS-Prefetch-Control关闭
xDownloadOptionsX-Download-OptionsnoopenTrue
xFrameOptionsX-Frame-OptionsSAMEORIGINTrue
xPermittedCrossDomainPoliciesX-Permitted-Cross-Domain-Policies
xXssProtectionX-XSS-Protection0
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 添加到 scriptSrcstyleSrc 来为 scriptstyle 元素添加 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")
    },
  })
)

Hono 中文网 - 粤ICP备13048890号