资讯动态

在 Next.js 边缘中间件中集成 DataDome 机器人防护:从一键部署到源码级原理

发布时间:2026/9/18 17:41:05 来源:尧图企业网站定制
在 Next.js 边缘中间件中集成 DataDome 机器人防护从一键部署到源码级原理【免费下载链接】examplesEnjoy our curated collection of examples and solutions. Use these patterns to build your own robust and scalable applications.项目地址: https://gitcode.com/GitHub_Trending/examples1/examplesDataDome 是一款实时机器人防护Bot Protection服务能为任意网站提供 bot 识别、验证码挑战与其他安全防护能力。本仓库中的edge-middleware/bot-protection-datadome示例演示了如何通过 Next.js Edge Middleware在请求到达应用之前就交给 DataDome 判定从而把防护逻辑下沉到边缘网络。阅读本文后你将掌握该示例的完整运行方式一键部署与本地克隆、三个演示路由的差异以及lib/datadome.ts中请求校验、超时兜底、响应头回写等核心实现的底层原理。示例概览在边缘完成机器人判定根据该示例 README 的说明DataDome 提供实时机器人防护以及其它安全防护能力而本模板的关键思路是在边缘Edge Middleware使用它中间件把每个受保护请求的上下文信息转发给 DataDome 的校验接口由 DataDome 返回放行或拦截的结论拦截时可直接改写rewrite到 DataDome 的验证码页面。模板自带一个在线演示地址https://edge-functions-bot-protection-datadome.vercel.app你可以通过它直观对比受保护页面与未受保护页面在响应头、延迟上的差异。三个演示路由受保护、被拦截与豁免示例页面共三个路由分别对应防护的三种状态源码位于 pages 目录路由页面文件行为/pages/index.tsx启用 DataDome 的首页正常用户可直接访问并展示响应中的x-datadome头/blockedpages/blocked.tsx强制触发拦截的演示页会把你送入验证码挑战/omitpages/omit.tsx完全不走 DataDome 的对照页便于观察防护带来的头部与延迟差异在blocked页面中README 页面文案提示验证码通常只需要通过一次之后刷新或再次访问不会再弹出除非你在 DevTools 的 Application → Storage → Cookies 中手动删除datadomecookie。这也侧面说明 DataDome 依靠客户端 cookie 记忆已通过验证的身份。快速开始示例 README 提供了两种使用方式。方式一一键部署到 Vercel点击 README 中的 Deploy with Vercel 按钮即可完成部署部署时会要求配置两个环境变量NEXT_PUBLIC_DATADOME_CLIENT_SIDE_KEY与DATADOME_SERVER_SIDE_KEY。该需求同时被 vercel.json 与 pages/_app.tsx 中的部署按钮配置所印证。方式二克隆到本地运行使用create-next-app配合 pnpm 拉取该示例pnpm create next-app --example https://github.com/vercel/examples/tree/main/edge-middleware/bot-protection-datadome bot-protection-datadome运行前需要有一个 DataDome 账号然后在示例目录中把环境变量示例文件复制为本地文件该文件会被 Git 忽略cp .env.example .env.local接着打开.env.local将环境变量替换为 DataDome 控制台中显示的密钥。README 指出密钥可在 DataDome 控制台的https://app.datadome.co/dashboard/config/protection/keys找到。最后启动开发服务器pnpm dev环境变量清单结合 lib/datadome.ts 与 pages/_app.tsx 的源码本示例实际读取的环境变量如下变量是否必填默认值用途DATADOME_SERVER_SIDE_KEY是无服务端密钥作为校验请求中的Key字段见datadome.ts中的requestData.KeyNEXT_PUBLIC_DATADOME_CLIENT_SIDE_KEY是无客户端密钥注入到tags.js脚本的window.ddjskey中DATADOME_TIMEOUT否300边缘侧等待 DataDome 响应的超时毫秒数DATADOME_ENDPOINT否https://api.datadome.coDataDome 校验 API 地址validateEndpoint()会自动补全https://前缀边缘中间件只保护需要保护的路由入口中间件位于 middleware.ts其核心逻辑非常精简export const config { // Its possible to run Datadome for all paths, but its better to take // advantage of pattern matching and only protect from bots where required. matcher: [/, /blocked], } export default async function middleware(req: NextRequest) { const { pathname } req.nextUrl // Force the page to be blocked by DataDome if (pathname /blocked) { req.headers.set(user-agent, BLOCKUA) } return datadome(req) }两点值得注意用matcher精确圈定保护范围源码注释明确说明虽然可以让 DataDome 覆盖所有路径但更优的做法是利用matcher模式匹配只在需要的地方启用防护。这也是为什么/omit路由不在matcher列表中——它天然绕过了中间件成为对照组。/blocked的拦截是伪造的该路由会把请求头中的user-agent强行改成BLOCKUA让 DataDome 把本应正常的请求判定为机器人从而演示拦截与验证码流程。中间件对datadome(req)的返回值有三种理解有响应且带 rewrite说明被拦截应返回该响应通常已改写为 DataDome 验证码页有响应但无 rewrite说明你不是机器人响应会携带 DataDome 的回写头无响应则直接放行。源码级拆解lib/datadome.ts 如何与 DataDome 通信中间件真正的重头戏在 lib/datadome.ts通过 tsconfig 中的lib/*路径别名引入。整个校验流程可以概括为静态资源放行 → 组装请求特征 → POST 校验 → 超时兜底 → 按状态码处理 → 回写响应头。1. 静态资源直接放行const DATADOME_URI_REGEX_EXCLUSION /\.(avi|flv|mka|mkv|mov|mp4|mpeg|mpg|mp3|flac|ogg|ogm|opus|wav|webm|webp|bmp|gif|ico|jpeg|jpg|png|svg|svgz|swf|eot|otf|ttf|woff|woff2|css|less|js|map)$/i对图片、音视频、字体、样式表、脚本等静态资源直接return不占用 DataDome 配额也避免边缘侧为每个静态请求增加额外延迟。2. 组装完整的请求特征上报requestData把一次 HTTP 请求的几乎所有上下文方法、路径、查询参数、Host、各协议头、Cookie 长度、sec-ch-ua*客户端提示、sec-fetch-*等收集起来POST 到DATADOME_ENDPOINT /validate-request/。其中两个细节很有参考价值客户端 IP 的取法代码注释说明按规范应取x-real-ip但它在 Edge Middleware 上不可用因此退而使用x-forwarded-for的第一段本地无此头时回退到127.0.0.1注释同时提醒本地调试时 DataDome 通常不会拦截除非使用真实 IP。字段长度裁剪truncateRequestData维护了一张字段长度上限表如useragent: 768、referer: 1024、request: 2048xforwardedforip为-512表示保留尾部超长字段会被截断避免上报体过大。3. 超时兜底Promise.race 竞速const timeoutPromise new Promise((resolve, reject) { setTimeout(() { reject(new Error(Datadome timeout)) }, DATADOME_TIMEOUT) }) dataDomeRes (await Promise.race([ dataDomeReq, timeoutPromise, ])) as NextResponse当 DataDome 服务不可用或响应过慢时Promise.race会以DATADOME_TIMEOUT默认 300ms触发超时代码捕获异常后console.error并return即放行请求。这是一个典型的fail-open设计防护服务故障不应拖垮正常业务宁可暂时放行也不阻塞用户。4. 按状态码分流处理switch (dataDomeRes.status) { case 400: // Something is wrong with our authentication return case 200: case 301: case 302: case 401: case 403: let res NextResponse.next() if (dataDomeRes.status ! 200) { // blocked! res new Response(dataDomeRes.body, {status: dataDomeRes.status}) as NextResponse ... } ... }400说明服务端密钥等认证信息有问题日志输出statusText与响应体后放行200未拦截构造NextResponse.next()继续正常处理301 / 302 / 401 / 403被拦截直接透传 DataDome 的响应体与状态码通常是验证码页面。命中 bot 时还会通过x-datadome-isbot、x-datadome-botname、x-datadome-ruletype打印出机器人的名称与命中规则类型。5. 回写 DataDome 响应头与 Cookie 域修复DataDome 的响应通过x-datadome-headers头声明需要回写到浏览器的头列表toHeaders会逐一取出并合并进最终响应。其中内置了一个知名 bug 的 workaround当 DataDome 返回的set-cookie把域设置为整个公共后缀.vercel.app时浏览器会拒绝写入该 cookie因此代码将其改写为Domain${req.headers.get(host)}保证datadomecookie 能正确种到当前域名下。另外源码中res.headers.set(x-datadome-latency, ...)这行带有注释该延迟头仅为演示目的而加生产环境并非必需。客户端脚本注入验证码与指纹的浏览器侧配合DataDome 的防护并不只有服务端判定浏览器侧脚本同样关键。pages/_app.tsx 使用next/script以lazyOnload策略加载两个脚本脚本地址定义在 lib/constants.tsexport const DATADOME_TAGS https://js.datadome.co/tags.js export const DATADOME_JS https://api-js.datadome.co/js/注入方式如下Script strategylazyOnload idload-datadome{ window.ddjskey ${process.env.NEXT_PUBLIC_DATADOME_CLIENT_SIDE_KEY} window.ddoptions { endpoint: ${DATADOME_JS} } }/Script Script src{DATADOME_TAGS} strategylazyOnload /ddjskey使用客户端密钥NEXT_PUBLIC_DATADOME_CLIENT_SIDE_KEY带NEXT_PUBLIC_前缀才能被 Next.js 暴露到浏览器ddoptions.endpoint指向 DataDome 的 JS API 地址两个脚本都采用lazyOnload策略避免阻塞页面首屏渲染。页面如何直观展示防护效果components/headers.tsx 是页面上的调试组件它对指定路径发起HEAD请求读取响应的x-datadome与x-datadome-latency两个头连同实测延迟一并 JSON 展示。这样访问/受保护与/omit未受保护时你能直接看到受保护页面多出x-datadome相关的响应头x-datadome-latency与页面整体延迟的差异即边缘侧引入 DataDome 校验的额外开销可结合浏览器 DevTools Network 面板进一步确认。部署与工程化配置项目脚本在 package.json 中定义dev/build/start/lint依赖方面使用next、react、react-dom以及vercel/examples-ui示例 UI 库。vercel.json 中指定了pnpm turbo build作为构建命令并用turbo-ignore实现无相关变更不触发构建的增量部署优化。小结与生产实践建议回顾本示例可以提炼出几条可直接复用的经验在边缘做防护通过matcher精确控制保护范围静态资源与无关路由直接放行兼顾安全与性能fail-open 超时策略Promise.race 默认 300ms 超时防护服务异常时优雅降级不阻塞正常流量密钥分级DATADOME_SERVER_SIDE_KEY只存在于服务端中间件内使用浏览器侧只暴露NEXT_PUBLIC_DATADOME_CLIENT_SIDE_KEY响应头透传DataDome 通过x-datadome-headers声明需要回写的头含 cookie并需注意公共后缀域名的 cookie 兼容问题演示辅助头按需取舍x-datadome-latency属于演示用途生产环境应评估是否需要暴露。如果你想在自己的 Next.js 应用中接入 DataDome最直接的方式就是克隆本示例配置好两个密钥环境变量再按需调整middleware.ts中的matcher覆盖范围即可。【免费下载链接】examplesEnjoy our curated collection of examples and solutions. Use these patterns to build your own robust and scalable applications.项目地址: https://gitcode.com/GitHub_Trending/examples1/examples创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价