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(删除标头)True
contentSecurityPolicyContent-Security-Policy用法:设置内容安全策略无设置
contentSecurityPolicyReportOnlyContent-Security-Policy-Report-Only用法:设置内容安全策略无设置
crossOriginEmbedderPolicyCross-Origin-Embedder-Policyrequire-corp
crossOriginResourcePolicyCross-Origin-Resource-Policysame-originTrue
crossOriginOpenerPolicyCross-Origin-Opener-Policysame-originTrue
originAgentClusterOrigin-Agent-Cluster?1True
referrerPolicyReferrer-Policyno-referrerTrue
reportingEndpointsReporting-Endpoints用法:设置内容安全策略无设置
reportToReport-To用法:设置内容安全策略无设置
strictTransportSecurityStrict-Transport-Securitymax-age=15552000;includeSubDomainsTrue
xContentTypeOptionsX-Content-Type-OptionsnosniffTrue
xDnsPrefetchControlX-DNS-Prefetch-ControloffTrue
xDownloadOptionsX-Download-OptionsnoopenTrue
xFrameOptionsX-Frame-OptionsSAMEORIGINTrue
xPermittedCrossDomainPoliciesX-Permitted-Cross-Domain-PoliciesnoneTrue
xXssProtectionX-XSS-Protection0True
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',
      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 来将 nonce 属性 添加到 scriptstyle 元素:

¥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 v4.7 中文网 - 粤ICP备13048890号