You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让Next.js后端仅接收Chrome扩展后台脚本的安全请求

问题:限制Next.js后端仅接收Chrome扩展后台脚本的请求?

我正在开发一个集成Chrome扩展功能的网站,采用Next Auth进行身份验证,需要从扩展端验证用户是否已登录/持有Next Auth令牌。目前的流程是从网站(本地localhost)的Cookie中获取令牌,发送到content.js,再在请求Next.js后端时把令牌放进Authorization请求头里。

Content脚本代码

async function run() {
  const response = await chrome.runtime.sendMessage({ type: "REQ_COOKIE" })
  const cookies = response.cookies as chrome.cookies.Cookie[]
  console.log(cookies)

  if (response.cookies.length > 0) {
    const authCookie = cookies.find(
      (cookie) => cookie.name == "__Secure-next-auth.session-token"
    ).value
    console.log(authCookie)
    const tokenString = `Bearer ${authCookie}`
    fetch("http://localhost:3000/api/auth", {
      headers: { Authorization: tokenString }
    })
  }
}
run()

后端代码

import type { NextRequest } from "next/server";
import { NextResponse } from "next/server";
import { getToken } from "next-auth/jwt";
import { env } from "@/env";
import { cookies } from "next/headers";

export async function OPTIONS(req: NextRequest) {
  return new NextResponse("", {
    headers: {
      "Access-Control-Allow-Origin": "*", // replace "*" with your actual origin
      "Access-Control-Allow-Credentials": "true",
      "Access-Control-Allow-Methods": "GET",
      "Access-Control-Allow-Headers": "Authorization",
    },
  });
}

export async function GET(req: NextRequest) {
  console.log(req.headers.get("Authorization"));
  const token = await getToken({ req, secret: env.NEXTAUTH_SECRET });
  if (token) {
    console.log(token);
    return new NextResponse("Successfull yay", {
      headers: {
        "Access-Control-Allow-Origin": "*",
        "Access-Control-Allow-Credentials": "true",
        "Access-Control-Allow-Methods": "GET",
        "Access-Control-Allow-Headers": "Authorization",
      },
    });
  } else {
    return new Response("Not verified", {
      status: 401,
      statusText: "Unauthorized",
      headers: {
        "Access-Control-Allow-Origin": "*", 
        "Access-Control-Allow-Credentials": "true",
        "Access-Control-Allow-Methods": "GET",
        "Access-Control-Allow-Headers": "Authorization",
      },
    });
  }
}

请问是否可以配置后端,使其仅接收来自Chrome扩展后台脚本的请求?


解决方案

可以通过两种核心方式实现后端仅接收Chrome扩展的请求,推荐结合使用提升安全性:

方法一:验证Chrome扩展唯一ID

Chrome扩展的后台/内容脚本可以携带自身的唯一ID,后端通过校验这个ID实现访问限制:

  1. 修改扩展端请求,添加自定义头
    在content脚本的fetch请求中,带上扩展ID的自定义头:
fetch("http://localhost:3000/api/auth", {
  headers: {
    Authorization: tokenString,
    "X-Chrome-Extension-Id": chrome.runtime.id // 自动获取当前扩展ID
  }
})
  1. 后端添加ID校验逻辑
    先定义你的扩展ID(可以从Chrome扩展管理页面查看,或通过manifest.json的key字段固定ID),然后在接口中校验:
// 替换为你的Chrome扩展ID
const ALLOWED_EXTENSION_ID = "abcdefghijklmnopqrstuvwxyzabcdef";

export async function OPTIONS(req: NextRequest) {
  const extensionId = req.headers.get("X-Chrome-Extension-Id");
  if (extensionId !== ALLOWED_EXTENSION_ID) {
    return new Response("Forbidden", { status: 403 });
  }
  
  return new NextResponse("", {
    headers: {
      "Access-Control-Allow-Origin": "*",
      "Access-Control-Allow-Credentials": "true",
      "Access-Control-Allow-Methods": "GET",
      "Access-Control-Allow-Headers": "Authorization,X-Chrome-Extension-Id",
    },
  });
}

export async function GET(req: NextRequest) {
  const extensionId = req.headers.get("X-Chrome-Extension-Id");
  if (extensionId !== ALLOWED_EXTENSION_ID) {
    return new Response("Forbidden", { status: 403 });
  }

  // 原有Next Auth令牌校验逻辑
  console.log(req.headers.get("Authorization"));
  const token = await getToken({ req, secret: env.NEXTAUTH_SECRET });
  if (token) {
    console.log(token);
    return new NextResponse("Successfull yay", {
      headers: {
        "Access-Control-Allow-Origin": "*",
        "Access-Control-Allow-Credentials": "true",
        "Access-Control-Allow-Methods": "GET",
        "Access-Control-Allow-Headers": "Authorization,X-Chrome-Extension-Id",
      },
    });
  } else {
    return new Response("Not verified", {
      status: 401,
      statusText: "Unauthorized",
      headers: {
        "Access-Control-Allow-Origin": "*",
        "Access-Control-Allow-Credentials": "true",
        "Access-Control-Allow-Methods": "GET",
        "Access-Control-Allow-Headers": "Authorization,X-Chrome-Extension-Id",
      },
    });
  }
}

方法二:验证请求Origin为Chrome扩展URL

Chrome扩展的请求Origin格式为chrome-extension://你的扩展ID,后端直接校验这个Origin:

  1. 后端添加Origin校验逻辑
// 替换为你的Chrome扩展Origin
const ALLOWED_EXTENSION_ORIGIN = "chrome-extension://abcdefghijklmnopqrstuvwxyzabcdef";

export async function OPTIONS(req: NextRequest) {
  const origin = req.headers.get("Origin");
  if (origin !== ALLOWED_EXTENSION_ORIGIN) {
    return new Response("Forbidden", { status: 403 });
  }
  
  return new NextResponse("", {
    headers: {
      "Access-Control-Allow-Origin": ALLOWED_EXTENSION_ORIGIN, // 不要用*,和Credentials冲突
      "Access-Control-Allow-Credentials": "true",
      "Access-Control-Allow-Methods": "GET",
      "Access-Control-Allow-Headers": "Authorization",
    },
  });
}

export async function GET(req: NextRequest) {
  const origin = req.headers.get("Origin");
  if (origin !== ALLOWED_EXTENSION_ORIGIN) {
    return new Response("Forbidden", { status: 403 });
  }

  // 原有Next Auth令牌校验逻辑...
}

注意事项

  • 固定扩展ID:可以通过在manifest.json中添加key字段(从已打包扩展导出),避免开发和生产环境ID不一致。
  • CORS规则:不要同时设置Access-Control-Allow-Origin: *和Access-Control-Allow-Credentials: true,这不符合CORS规范,验证Origin后直接指定允许的Origin值即可。
  • 双重验证:建议同时校验扩展ID和Origin,进一步提升接口安全性。

内容的提问来源于stack exchange,提问作者DevEnma

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 05:43:11