npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@huyooo/hono-middlewares

v0.1.18

Published

A collection of useful Hono middlewares

Readme

⚡️ Hono Middlewares

一个为 Hono 框架提供常用中间件集合的库,包含日志、认证、验证、错误处理等常用功能。

✨ 特性

  • 🚀 开箱即用: 提供常用的中间件集合,无需额外配置
  • 🔧 配置驱动: 通过统一的配置对象管理所有中间件
  • 🛡️ 类型安全: 完整的 TypeScript 支持,智能类型提示
  • 📦 模块化: 可以独立使用各个中间件,也可以使用综合包
  • 🎯 标准化错误: 重新封装的中间件(bodyLimit、timeout、csrf、ipRestriction、rateLimiter)提供统一的错误格式
  • 🎯 生产就绪: 包含安全、性能、监控等生产环境必需功能
  • ⚡️ 高性能: 基于 Hono 的高性能中间件架构
  • 🔒 安全优先: 内置 CORS、CSRF、安全头部等安全功能
  • 📊 监控友好: 内置请求 ID、性能监控、结构化日志

📦 安装

# 安装 hono-middlewares
npm install @huyooo/hono-middlewares

# 安装 peer dependency
npm install hono

🚀 快速开始

💡 提示: 我们重新封装了 bodyLimittimeoutcsrfipRestrictionrateLimiter 中间件,它们现在都提供标准化的错误格式,与我们的错误处理系统完全兼容。

使用综合中间件包(推荐)

import { Hono } from 'hono'
import { middlewareBundle } from '@huyooo/hono-middlewares'

const app = new Hono()

// 使用默认配置
app.use('*', middlewareBundle())

// 或者自定义配置
app.use('*', middlewareBundle({
  logging: {
    service: 'my-api-service',
    enablePrettyPrint: false,
  },
  cors: {
    origin: ['https://yourdomain.com'],
    credentials: true,
  },
  rateLimit: {
    limit: 1000,
  },
}))

app.get('/', (c) => c.json({ message: 'Hello World!' }))

环境区分配置(推荐)

import { Hono } from "hono";
import { middlewareBundle } from "@huyooo/hono-middlewares";

const app = new Hono();

const isDev = process.env.NODE_ENV === 'development';
const isProd = process.env.NODE_ENV === 'production';

app.use("*", middlewareBundle({
  logging: {
    service: "my-api-service",
    enablePrettyPrint: isDev,
  },
  cors: {
    origin: isProd ? ['https://yourdomain.com'] : '*',
    credentials: isProd,
    // 其他选项使用默认值:allowMethods, allowHeaders, exposeHeaders, maxAge
  },
  rateLimit: {
    limit: isProd ? 1000 : 10000,
  },
  prettyJSON: { enabled: isDev },
  timing: { enabled: isDev },
  csrf: { enabled: isProd },
}));

使用独立中间件

import { Hono } from 'hono'

// 从主包导入核心中间件(不包含官方中间件)
import { 
  auth, 
  schemaValidator, 
  t, 
  errorHandler,
  rateLimiter,
  middlewareBundle
} from '@huyooo/hono-middlewares'

// 从 core 包导入官方中间件
import {
  cors,
  secureHeaders,
  timing,
  requestId,
  compress,
  bodyLimit,
  timeout,
  appendTrailingSlash
} from '@huyooo/hono-middlewares/core'

const app = new Hono()

// 错误处理 app.use('*', errorHandler())

// CORS 配置 app.use('*', cors({ origin: ['https://yourdomain.com'], credentials: true, }))

// 安全头部 app.use('*', secureHeaders())

// 性能监控 app.use('', timing()) app.use('', requestId())

// 压缩响应 app.use('*', compress())

// 请求体大小限制 app.use('*', bodyLimit({ maxSize: 1024 * 1024, // 1MB }))

// 请求超时 app.use('*', timeout({ timeout: 5000, // 5秒 }))

// 尾部斜杠处理 app.use('*', appendTrailingSlash())

// 速率限制 app.use('*', rateLimiter({ windowMs: 15 * 60 * 1000, // 15分钟 limit: 100, // 限制100个请求 }))

// 认证中间件 app.get('/protected', auth(), (c) => { const userInfo = c.get('userInfo') return c.json({ message: 'Protected route', userInfo }) })

// API Key 认证中间件 app.get('/api/protected', apiKeyAuth(), (c) => { const apiKeyInfo = c.get('apiKeyInfo') const userInfo = c.get('userInfo') return c.json({ message: 'API Key protected route', apiKeyInfo, userInfo }) })

// 条件认证中间件 app.use('/api/*', conditionalAuth()) app.get('/api/data', (c) => { // 根据认证方式自动选择 API Key 或 JWT 认证 const apiKeyInfo = c.get('apiKeyInfo') const userInfo = c.get('userInfo') return c.json({ message: 'Conditionally authenticated', apiKeyInfo, userInfo }) })

// 参数验证 const userSchema = t.Object({ name: t.String(), email: t.String({ format: 'email' }), age: t.Number({ minimum: 18 }) })

app.post('/users', schemaValidator('json', userSchema), (c) => { const data = c.req.valid('json') return c.json({ message: 'User created', data }) })


## 📚 可用中间件

### 核心中间件

| 中间件 | 描述 | 导入方式 |
|--------|------|----------|
| `auth` | JWT 认证中间件 | `import { auth } from '@huyooo/hono-middlewares'` |
| `apiKeyAuth` | API Key 认证中间件 | `import { apiKeyAuth } from '@huyooo/hono-middlewares'` |
| `conditionalAuth` | 条件认证中间件 | `import { conditionalAuth } from '@huyooo/hono-middlewares'` |
| `pinoLogger` | Pino 日志中间件 | `import { pinoLogger } from '@huyooo/hono-middlewares'` |
| `requestLogger` | 请求日志中间件 | `import { requestLogger } from '@huyooo/hono-middlewares'` |
| `schemaValidator` | 参数验证中间件 | `import { schemaValidator, t } from '@huyooo/hono-middlewares'` |
| `errorHandler` | 错误处理中间件 | `import { errorHandler } from '@huyooo/hono-middlewares'` |

### Hono 官方中间件

| 中间件 | 描述 | 导入方式 |
|--------|------|----------|
| `prettyJSON` | JSON 美化输出 | `import { prettyJSON } from '@huyooo/hono-middlewares/core'` |
| `cors` | CORS 跨域支持 | `import { cors } from '@huyooo/hono-middlewares/core'` |
| `secureHeaders` | 安全头部设置 | `import { secureHeaders } from '@huyooo/hono-middlewares/core'` |
| `csrf` | CSRF 保护 | `import { csrf } from '@huyooo/hono-middlewares/core'` |
| `logger` | 基础日志中间件 | `import { logger } from '@huyooo/hono-middlewares/core'` |
| `timing` | 性能监控 | `import { timing } from '@huyooo/hono-middlewares/core'` |
| `requestId` | 请求 ID 生成 | `import { requestId } from '@huyooo/hono-middlewares/core'` |
| `compress` | 响应压缩 | `import { compress } from '@huyooo/hono-middlewares/core'` |
| `bodyLimit` | 请求体大小限制(标准化错误格式) | `import { bodyLimit } from '@huyooo/hono-middlewares/core'` |
| `timeout` | 请求超时控制(标准化错误格式) | `import { timeout } from '@huyooo/hono-middlewares/core'` |
| `csrf` | CSRF 保护(标准化错误格式) | `import { csrf } from '@huyooo/hono-middlewares/core'` |
| `ipRestriction` | IP 访问限制(标准化错误格式) | `import { ipRestriction } from '@huyooo/hono-middlewares/core'` |
| `appendTrailingSlash` | 添加尾部斜杠 | `import { appendTrailingSlash } from '@huyooo/hono-middlewares/core'` |
| `trimTrailingSlash` | 移除尾部斜杠 | `import { trimTrailingSlash } from '@huyooo/hono-middlewares/core'` |
| `ipRestriction` | IP 访问限制 | `import { ipRestriction } from '@huyooo/hono-middlewares/core'` |

### 第三方中间件

| 中间件 | 描述 | 导入方式 |
|--------|------|----------|
| `rateLimiter` | 速率限制 | `import { rateLimiter } from '@huyooo/hono-middlewares'` |

## 🔧 配置说明

### middlewareBundle 默认配置

为了提供更好的开箱即用体验和避免常见的兼容性问题,我们对默认配置进行了优化:

```typescript
const defaultConfig = {
  // 日志配置 - 默认启用
  logging: {
    enabled: true,
    service: '@huyooo/hono-middlewares',
    enablePrettyPrint: false,
  },
  
  // CORS 配置 - 默认启用,允许所有来源
  cors: {
    enabled: true,
    origin: '*',
    allowMethods: ['GET', 'HEAD', 'PUT', 'POST', 'DELETE', 'PATCH', 'OPTIONS'],
    allowHeaders: [],
    exposeHeaders: [],
    credentials: undefined,
    maxAge: undefined,
  },
  
  // 安全头部 - 默认关闭,避免与 CORS 冲突
  secureHeaders: {
    enabled: false,
  },
  
  // 性能监控 - 默认启用
  timing: {
    enabled: true,
  },
  requestId: {
    enabled: true,
  },
  
  // 速率限制 - 默认启用
  rateLimit: {
    enabled: true,
    limit: 100,
    windowMs: 15 * 60 * 1000,
  },
  
  // 压缩 - 默认关闭,避免 CORS 问题和其他兼容性问题
  compress: {
    enabled: false,
    encoding: 'gzip',
  },
  
  // 其他中间件 - 默认关闭
  csrf: { enabled: false },
  bodyLimit: { enabled: false },
  ipRestriction: { enabled: false },
  timeout: { enabled: false },
  trailingSlash: { enabled: false },
  errorHandling: { enabled: true },
  prettyJSON: { enabled: false },
}

重要变更说明

🔧 默认配置优化

  1. 安全头部默认关闭 (secureHeaders.enabled: false)

    • 原因: 避免与 CORS 的 origin: '*' 配置冲突
    • 影响: 生产环境需要手动启用安全头部
    • 建议: 生产环境建议启用并配置具体的安全策略
  2. 压缩默认关闭 (compress.enabled: false)

    • 原因: 避免与 CORS 处理和其他兼容性问题
    • 影响: 响应不会被自动压缩
    • 建议: 如需压缩,可手动启用或使用反向代理处理
  3. CORS 默认允许所有来源 (cors.origin: '*')

    • 原因: 提供开箱即用的跨域支持
    • 影响: 开发环境友好,但生产环境需要配置具体域名
    • 建议: 生产环境必须设置具体的 origin

🎯 推荐配置

开发环境:

app.use('*', middlewareBundle({
  logging: {
    service: 'my-api-dev',
    enablePrettyPrint: true,
  },
  cors: {
    origin: '*', // 开发环境允许所有来源
  },
  prettyJSON: { enabled: true },
  timing: { enabled: true },
}))

生产环境:

app.use('*', middlewareBundle({
  logging: {
    service: 'my-api-prod',
    enablePrettyPrint: false,
  },
  cors: {
    origin: ['https://yourdomain.com'], // 生产环境指定具体域名
    credentials: true,
  },
  secureHeaders: { enabled: true }, // 生产环境启用安全头部
  compress: { enabled: true }, // 生产环境启用压缩
  csrf: { enabled: true }, // 生产环境启用 CSRF 保护
  rateLimit: {
    limit: 1000, // 生产环境更严格的限制
  },
}))

middlewareBundle 配置

import { middlewareBundle, type MiddlewareBundleConfig } from '@huyooo/hono-middlewares'

const config: MiddlewareBundleConfig = {
  // 日志配置
  logging: {
    enabled: true,
    service: 'my-api',
    enablePrettyPrint: false,
  },
  
  // CORS 配置
  cors: {
    enabled: true,
    origin: ['https://yourdomain.com'],
    credentials: true,
  },
  
  // 安全头部
  secureHeaders: {
    enabled: true,
  },
  
  // 性能监控
  timing: {
    enabled: true,
  },
  requestId: {
    enabled: true,
  },
  
  // 速率限制
  rateLimit: {
    enabled: true,
    limit: 1000,
    windowMs: 15 * 60 * 1000,
  },
  
  // IP 限制
  ipRestriction: {
    enabled: true,
    getConnInfo: getConnInfo, // 必须提供,根据运行环境选择
    denyList: ["192.168.1.100", "10.0.0.0/8"],
    allowList: ["127.0.0.1", "::1", "192.168.1.0/24"],
  },
  
  // 其他配置...
}

app.use('*', middlewareBundle(config))

CORS 默认配置

CORS 中间件的默认配置与 Hono 官方 CORS 中间件保持一致:

cors: {
  enabled: true,
  origin: "*",                    // 允许所有来源
  allowMethods: [                 // 允许的 HTTP 方法
    "GET", "HEAD", "PUT", 
    "POST", "DELETE", "PATCH"
  ],
  allowHeaders: [],               // 允许的请求头(空数组,自动处理)
  exposeHeaders: [],              // 暴露的响应头(空数组)
  credentials: undefined,         // 是否允许携带凭证(默认不设置)
  maxAge: undefined,             // 预检请求缓存时间(默认不设置)
}

重要提示:

  • 生产环境建议设置具体的 origin 而不是 "*"
  • credentials: true 时不能使用 origin: "*",必须指定具体域名
  • allowHeaders 为空数组时会自动处理 Access-Control-Request-Headers 请求头

🌐 CORS 跨域配置

生产环境配置

app.use("*", middlewareBundle({
  // 日志配置
  logging: {
    service: "my-api-production",
    enablePrettyPrint: false,
  },
  
  // 安全头部配置 - 支持跨域
  secureHeaders: {
    contentSecurityPolicy: "default-src 'self'; connect-src *;",
    xFrameOptions: "SAMEORIGIN",
  },
  
  // 速率限制
  rateLimit: {
    limit: 1000,
  },
  
  // 超时和请求体大小限制
  timeout: {
    enabled: true,
    timeout: 30000,
  },
  bodyLimit: {
    enabled: true,
  },

  // 性能监控跨域
  timing: {
    crossOrigin: true,
  },
  
  // 使用默认值:cors: origin: "*" (允许所有跨域)
}));

开发环境配置

app.use("*", middlewareBundle({
  cors: {
    origin: "*",
  },
  secureHeaders: {
    contentSecurityPolicy: "default-src 'self'; connect-src *;",
    xFrameOptions: "SAMEORIGIN",
  },
}));

HTTPS/HTTP 混合内容问题

如果遇到 Access to XMLHttpRequest has been blocked by CORS policy 错误:

// 方案1:使用代理
// vite.config.js
export default {
  server: {
    proxy: {
      '/api': {
        target: 'https://your-api.com',
        changeOrigin: true,
      }
    }
  }
}

Content Security Policy 配置说明

API服务推荐配置:

contentSecurityPolicy: "default-src 'self'; connect-src *;"

各部分说明:

  • default-src 'self' - 默认只允许同源资源
  • connect-src * - 允许所有跨域API调用

其他配置选项:

// 最宽松配置(开发环境,不推荐生产环境)
contentSecurityPolicy: "default-src * 'unsafe-inline' 'unsafe-eval';"

// 最严格配置(生产环境,可能影响功能)
contentSecurityPolicy: "default-src 'self'; connect-src 'self' https://yourdomain.com;"

// 完整跨域配置(包含所有资源类型)
contentSecurityPolicy: "default-src 'self'; connect-src *; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src * data:; font-src * data:;"

API服务配置说明:

  • 纯API接口 - 只需要 connect-src * 允许跨域调用
  • 无前端资源 - 不需要 script-srcstyle-src 等配置
  • 安全性高 - 最小化配置,减少安全风险

安全考虑:

  • 'unsafe-inline' - 允许内联脚本,存在XSS风险
  • 'unsafe-eval' - 允许动态代码执行,存在安全风险
  • * - 允许所有来源,降低安全性

推荐策略:

  1. API服务 - 使用 default-src 'self'; connect-src *;
  2. 开发环境 - 可以使用最宽松配置
  3. 生产环境 - 根据实际需求调整,优先考虑安全性

🎯 标准化错误格式

为了提供一致的错误处理体验,我们对某些中间件进行了重新封装,确保它们返回标准化的错误格式。

标准错误响应格式

所有重新封装的中间件都使用统一的错误响应格式:

{
  "success": false,
  "code": 41301,        // 错误代码
  "message": "请求体过大",  // 中文错误消息
  "data": null
}

重新封装的中间件

bodyLimit 中间件

原始 Hono 中间件问题:

  • 返回简单的 "Payload Too Large" 文本响应
  • 错误格式不一致,难以统一处理

我们的改进:

  • 返回标准化的 JSON 错误响应
  • 使用 CodeEnum.RequestBodyTooLarge (41301)
  • 支持自定义错误消息
  • 保持与 Hono 官方中间件完全兼容
import { bodyLimit } from '@huyooo/hono-middlewares/core'

// 基础使用
app.use('*', bodyLimit({ maxSize: 1024 * 1024 })) // 1MB

// 自定义错误消息
app.use('*', bodyLimit({ 
  maxSize: 1024 * 1024,
  message: '文件大小不能超过 1MB'
}))

timeout 中间件

原始 Hono 中间件问题:

  • 抛出 HTTPException,错误格式不统一
  • 难以在全局错误处理器中统一处理

我们的改进:

  • 返回标准化的 JSON 错误响应
  • 使用 CodeEnum.GatewayTimeout (50401)
  • 支持自定义错误消息
  • 保持向后兼容性
import { timeout } from '@huyooo/hono-middlewares/core'

// 基础使用(向后兼容)
app.use('*', timeout(5000)) // 5秒

// 选项对象配置
app.use('*', timeout({ 
  duration: 5000,
  message: '请求处理时间过长,请稍后重试'
}))

csrf 中间件

原始 Hono 中间件问题:

  • 错误响应格式不统一
  • 难以在全局错误处理器中统一处理

我们的改进:

  • 返回标准化的 JSON 错误响应
  • 使用 CodeEnum.UnauthorizedAccess (40901)
  • 支持自定义错误消息
  • 保持与 Hono 官方中间件完全兼容
import { csrf } from '@huyooo/hono-middlewares/core'

// 基础使用
app.use('*', csrf())

// 自定义 origin 配置
app.use('*', csrf({ 
  origin: 'https://yourdomain.com'
}))

// 自定义错误消息
app.use('*', csrf({ 
  origin: 'https://yourdomain.com',
  message: 'CSRF 验证失败,请检查请求来源'
}))

ipRestriction 中间件

原始 Hono 中间件问题:

  • 错误响应格式不统一
  • 难以在全局错误处理器中统一处理

我们的改进:

  • 返回标准化的 JSON 错误响应
  • 使用 CodeEnum.UnauthorizedAccess (40901)
  • 支持自定义错误消息
  • 保持与 Hono 官方中间件完全兼容
import { ipRestriction } from '@huyooo/hono-middlewares/core'

// 基础使用
app.use('*', ipRestriction({
  getConnInfo: getConnInfo
}))

// 配置 IP 限制规则
app.use('*', ipRestriction({
  getConnInfo: getConnInfo,
  denyList: ['192.168.1.100'],
  allowList: ['127.0.0.1', '::1']
}))

// 自定义错误消息
app.use('*', ipRestriction({
  getConnInfo: getConnInfo,
  denyList: ['192.168.1.100'],
  message: 'IP 地址访问被拒绝'
}))

错误代码定义

export enum CodeEnum {
  // ... 其他错误代码
  RequestBodyTooLarge = 41301,  // 请求体过大
  GatewayTimeout = 50401,       // 网关超时
  UnauthorizedAccess = 40901,   // 未授权访问(CSRF、IP限制等)
  TooManyRequests = 42901,      // 请求过于频繁(速率限制)
  // ... 其他错误代码
}

优势

  1. 一致性: 所有中间件错误都使用相同的响应格式
  2. 可维护性: 统一的错误处理逻辑,易于维护和扩展
  3. 用户体验: 前端可以统一处理错误响应
  4. 向后兼容: 保持与原始 Hono 中间件的 API 兼容性
  5. 类型安全: 完整的 TypeScript 类型支持

🔑 认证中间件详细说明

apiKeyAuth 中间件

API Key 认证中间件,用于验证 API Key 和 Secret Key 的有效性。

功能特性

  • 🔐 双重验证: 验证 API Key ID 和 Secret Key
  • 🌐 外部验证: 调用外部 API 进行验证
  • 📊 上下文存储: 将验证信息存储在 Hono Context 中
  • 🛡️ 错误处理: 标准化的错误响应格式
  • 🔄 用户信息: 自动获取并存储用户信息(如果可用)

基本使用

import { apiKeyAuth } from '@huyooo/hono-middlewares'

// 基础使用
app.use('/api/*', apiKeyAuth())

// 在路由中使用
app.get('/api/protected', apiKeyAuth(), (c) => {
  const apiKeyInfo = c.get('apiKeyInfo')
  const userInfo = c.get('userInfo')
  return c.json({ message: 'Protected route', apiKeyInfo, userInfo })
})

请求头要求

// 必需在请求头中包含
headers: {
  'x-api-key': 'your-api-key-id',
  'x-secret-key': 'your-secret-key'
}

验证流程

  1. 检查请求头: 验证 x-api-keyx-secret-key 是否存在
  2. 调用验证 API: 向 https://ones.huyooo.com/restfulApi/verify/apiKey 发送验证请求
  3. 存储验证结果: 将验证信息存储在 c.get('apiKeyInfo')
  4. 存储用户信息: 如果验证成功且包含用户信息,存储在 c.get('userInfo')

Context 变量

// API Key 信息
interface ApiKeyInfo {
  apiKeyId: string
  verified: boolean
  timestamp: string
  creatorId: string
  data: any
}

// 用户信息(如果可用)
interface UserInfo {
  id: string
  email: string
  nickname: string
  // ... 其他用户字段
}

// 在路由中获取
app.get('/api/data', apiKeyAuth(), (c) => {
  const apiKeyInfo = c.get('apiKeyInfo') as ApiKeyInfo
  const userInfo = c.get('userInfo') as UserInfo | undefined
  
  return c.json({
    message: 'Success',
    apiKey: apiKeyInfo.apiKeyId,
    creator: apiKeyInfo.creatorId,
    user: userInfo
  })
})

错误处理

所有错误响应都使用标准格式,HTTP 状态码为 200:

// 缺少 API Key
{
  "success": false,
  "code": 40001,
  "message": "缺少 API Key ID",
  "data": null
}

// 缺少 Secret Key
{
  "success": false,
  "code": 40001,
  "message": "缺少 Secret Key",
  "data": null
}

// 验证失败
{
  "success": false,
  "code": 40101,
  "message": "API Key 验证失败",
  "data": null
}

// 网络错误
{
  "success": false,
  "code": 40101,
  "message": "API Key 验证请求失败",
  "data": null
}

使用场景

  1. API 服务认证: 为第三方应用提供 API 访问
  2. 微服务间通信: 服务间的身份验证
  3. 自动化脚本: 脚本和工具的 API 访问
  4. 移动应用: 移动应用的 API 认证

安全建议

  • 🔒 使用 HTTPS 传输 API Key 和 Secret Key
  • 🔑 定期轮换 Secret Key
  • 📝 记录 API Key 的使用日志
  • 🚫 不要在客户端代码中暴露 Secret Key
  • ⏰ 设置合理的 API Key 过期时间

auth 中间件

JWT 认证中间件,用于验证用户身份。

功能特性

  • 🔐 JWT 验证: 验证 Authorization header 中的 JWT token
  • 🆔 应用验证: 验证 app-id header 的有效性
  • 👤 用户信息: 获取并存储用户信息
  • 🛡️ 错误处理: 标准化的错误响应格式

基本使用

import { auth } from '@huyooo/hono-middlewares'

// 基础使用
app.use('/protected/*', auth())

// 在路由中使用
app.get('/protected/profile', auth(), (c) => {
  const userInfo = c.get('userInfo')
  return c.json({ message: 'User profile', userInfo })
})

请求头要求

// 必需在请求头中包含
headers: {
  'authorization': 'Bearer your-jwt-token',
  'app-id': 'your-application-id'
}

验证流程

  1. 检查请求头: 验证 authorizationapp-id 是否存在
  2. 调用用户 API: 向 https://ones.huyooo.com/restfulApi/users/profile 发送验证请求
  3. 存储用户信息: 将用户信息存储在 c.get('userInfo')

Context 变量

// 用户信息
interface UserInfo {
  id: string
  email: string
  nickname: string
  // ... 其他用户字段
}

// 在路由中获取
app.get('/protected/data', auth(), (c) => {
  const userInfo = c.get('userInfo') as UserInfo
  
  return c.json({
    message: 'Success',
    userId: userInfo.id,
    userEmail: userInfo.email
  })
})

错误处理

所有错误响应都使用标准格式,HTTP 状态码为 200:

// 缺少 Authorization header
{
  "success": false,
  "code": 40101,
  "message": "未携带authorization header",
  "data": null
}

// 缺少 app-id
{
  "success": false,
  "code": 40002,
  "message": "缺少必需的应用ID",
  "data": null
}

// 认证失败
{
  "success": false,
  "code": 40101,
  "message": "认证失败",
  "data": null
}

conditionalAuth 中间件

智能条件认证中间件,能够根据请求头中的 API Key 是否存在来自动选择不同的认证方式。

功能特性

  • 🤖 智能选择: 自动检测 API Key 存在性,选择相应认证方式
  • 🔄 双重认证: 支持 API Key 认证和 JWT 认证两种方式
  • 🎯 灵活配置: 可自定义 API Key 请求头名称
  • 🐛 调试支持: 可选的调试日志输出
  • 🛡️ 错误处理: 标准化的错误响应格式

认证逻辑

  1. 检测 API Key: 检查请求头中是否包含 x-api-key(可自定义)
  2. 选择认证方式:
    • 如果存在 API Key → 使用 apiKeyAuth() 中间件
    • 如果不存在 API Key → 使用 auth() 中间件
  3. 执行认证: 调用相应的认证中间件进行验证

基本使用

import { conditionalAuth } from '@huyooo/hono-middlewares'

// 基础使用(使用默认配置)
app.use('/api/*', conditionalAuth())

// 自定义配置
app.use('/api/*', conditionalAuth({
  apiKeyHeader: 'x-api-key',        // 自定义 API Key 请求头名称
  enableDebugLogs: true,            // 启用调试日志
  message: '自定义认证失败消息'      // 自定义错误消息
}))

配置选项

interface ConditionalAuthOptions {
  apiKeyHeader?: string              // API Key 请求头名称,默认 'x-api-key'
  enableDebugLogs?: boolean          // 是否启用调试日志,默认 false
  message?: string                   // 自定义错误消息
}

使用场景

  1. 混合认证系统: 同时支持 API Key 和 JWT 认证的应用
  2. 渐进式迁移: 从 API Key 认证迁移到 JWT 认证
  3. 多客户端支持: 不同客户端使用不同认证方式
  4. 开发测试: 开发环境使用 API Key,生产环境使用 JWT

请求示例

使用 API Key 认证:

curl -H "x-api-key: your-api-key" \
     -H "x-secret-key: your-secret-key" \
     https://api.example.com/data

使用 JWT 认证:

curl -H "authorization: Bearer your-jwt-token" \
     -H "app-id: your-app-id" \
     https://api.example.com/data

调试日志

启用调试日志后,会输出详细的认证流程信息:

app.use('/api/*', conditionalAuth({ enableDebugLogs: true }))

// 输出示例:
// [conditionalAuth] 中间件开始执行
// [conditionalAuth] 请求路径: /api/data
// [conditionalAuth] 请求方法: GET
// [conditionalAuth] 完整URL: https://api.example.com/api/data
// [conditionalAuth] 检测到 x-api-key: 存在
// [conditionalAuth] 执行 API Key 鉴权路径

错误处理

所有错误响应都使用标准格式,HTTP 状态码为 200:

{
  "success": false,
  "code": 40101,
  "message": "条件鉴权失败,请检查认证信息",
  "data": null
}

最佳实践

  1. 统一路由: 将需要认证的路由统一使用 conditionalAuth
  2. 调试开发: 开发环境启用调试日志,生产环境关闭
  3. 错误消息: 根据业务需求自定义错误消息
  4. 监控日志: 记录认证方式选择,便于分析和优化

🔒 IP 限制配置

IP 限制中间件基于 Hono 官方的 ip-restriction 中间件,支持 IPv4 和 IPv6 地址限制。

基本配置

import { getConnInfo } from '@hono/node-server/conninfo'; // Node.js 环境

app.use("*", middlewareBundle({
  ipRestriction: {
    enabled: true,
    getConnInfo: getConnInfo, // 必须提供,根据运行环境选择
    denyList: ["192.168.1.100", "10.0.0.0/8"],
    allowList: ["127.0.0.1", "::1", "192.168.1.0/24"],
  },
}));

支持的 IP 规则格式

IPv4

  • 192.168.2.0 - 静态 IP 地址
  • 192.168.2.0/24 - CIDR 表示法
  • * - 匹配所有地址

IPv6

  • ::1 - 静态 IP 地址
  • ::1/10 - CIDR 表示法
  • * - 匹配所有地址

不同环境的 getConnInfo

// Node.js 环境
import { getConnInfo } from '@hono/node-server/conninfo';

// Bun 环境
import { getConnInfo } from 'hono/bun';

// Deno 环境
import { getConnInfo } from 'hono/deno';

// Cloudflare Workers 环境
import { getConnInfo } from 'hono/cloudflare-workers';

配置说明

  • enabled: 是否启用 IP 限制
  • getConnInfo: 获取连接信息的函数(必须提供,根据运行环境选择)
  • denyList: 拒绝列表,拒绝这些 IP 访问
  • allowList: 允许列表,只允许这些 IP 访问(如果设置了 allowList,则只有列表中的 IP 可以访问)

使用场景

  1. 内网访问限制: 只允许特定网段的 IP 访问
  2. 黑名单: 拒绝特定 IP 或网段访问
  3. 白名单: 只允许特定 IP 或网段访问
  4. 安全防护: 防止恶意 IP 攻击

📖 更多示例

查看 examples/ 目录获取更多使用示例:

  • examples/basic-usage.ts - 基础使用示例
  • examples/commonMiddlewares-usage.ts - 综合中间件使用示例
  • examples/new-middlewares-usage.ts - 新中间件使用示例
  • examples/core-middlewares-usage.ts - 官方中间件单独使用示例
  • examples/package-import-demo.ts - 包导入方式演示
  • examples/cors-defaults-demo.ts - CORS默认值演示
  • examples/ip-restriction-usage.ts - IP 限制使用示例
  • examples/ip-restriction-environments.ts - 不同环境 IP 限制示例
  • examples/apiKeyAuth-usage.ts - API Key 认证使用示例
  • examples/conditionalAuth-usage.ts - 条件认证使用示例