Next.js 14中怎么使用 CORS

本文为翻译作品,原文链接:How to use CORS in Next.js 14

在深入研究 Next.js 中的 CORS 之前,让我们一起回顾一下总体思路,以建立牢固的基础认识。

跨源资源共享(或 CORS)是一种安全机制,用于保护网站免受跨源请求的影响。

简单来说,"来源"指的是除你自己的域以外的任何域。

此外,"来源"被正式定义如下:

<协议>://<域名>:<端口号>

端口号可以是可选的,例如 <协议>://<域名> 也足够了。

例如:www.example.com:443

请看下面的 CORS 操作,来源 x.com 尝试从来源 y.com 接收数据:

🗣️ 词语解释:

  1. x.com 发送预请求(也就是 HTTP OPTIONS 请求)以请求来自 y.com 的数据。
  2. y.com 随后检查请求的 Headers
  3. 如果启用了 CORS Headers 且 y.com 在白名单中,则向 x.com 发送数据。
  4. 如果禁用了 CORS Headers,或者 y.com 不在白名单中,则不向 x.com 发送数据。

那么你可能会问:"什么是 CORS Headers?"

有四个主要 CORS Headers 需要了解:

  • Access-Control-Allow-Origin --- 指定可以访问该资源的来源
  • Access-Control-Allow-Methods --- 添加到预检响应中,以指示允许的 HTTP 方法,如 GET、POST、PUT 等
  • Access-Control-Allow-Headers --- 在响应预检请求时返回,以指定当前请求中允许的 HTTP 头
  • Access-Control-Allow-Credentials --- 指示浏览器是否应在跨来源请求中包含诸如 cookies 或 HTTP 认证的凭证

现在我们已经熟悉了 CORS,及其在网页开发中的应用,让我们将这些理解应用到 Next.js 的项目中。

在 Next.js 中启用 CORS 的 3 种方式

请确保通过在终端窗口运行以下命令创建一个新的 Next.js 14 应用程序:

bash 复制代码
npx create-next-app@latest

1. Next.js 配置 Headers

在你的应用程序根目录下的 next.config.js 文件中,你可以配置异步的 headers() 键,带有所需的 CORS Headers:

javascript 复制代码
// next.config.js

/** @type {import('next').NextConfig} */
const nextConfig = {
    async headers() {
        return [
            {
                // 在这里,你可以使用正则表达式添加你的来源 URL。
                source: "<your-source-url(s)>",
                headers: [
                    { key: "Access-Control-Allow-Credentials", value: "true" },
                    // 在这里添加你的白名单来源
                    { key: "Access-Control-Allow-Origin", value: "<your-origin>" },
                    { key: "Access-Control-Allow-Methods", value: "GET,DELETE,PATCH,POST,PUT" },
                    { key: "Access-Control-Allow-Headers", value: "X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version" },
                ]
            }
        ]
    }
}

module.exports = nextConfig

注意:

  • 你可以使用路径正则表达式配置多个来源。例如,/api/:path* 将匹配所有 api 路径。
  • 你的来源将能够访问你的来源 URL API 数据;确保来源是可信任的。

2. 中间件

如果你需要在请求发送到你的来源之前应用 CORS Headers,则需要使用中间件。

在与你的 app/ 目录同级的位置,创建一个名为 middleware.ts 的文件,并使用以下模板代码:

javascript 复制代码
// src/middleware.ts 或 src/middleware.js

// https://blog.logrocket.com/using-cors-next-js-handle-cross-origin-requests/

import { NextResponse } from "next/server";

export function middleware() {
    // 检索当前响应
    const res = NextResponse.next()

    // 向响应中添加 CORS Headers
    res.headers.append('Access-Control-Allow-Credentials', "true")
    res.headers.append('Access-Control-Allow-Origin', '<your-origin>')
    res.headers.append('Access-Control-Allow-Methods', 'GET,DELETE,PATCH,POST,PUT')
    res.headers.append(
        'Access-Control-Allow-Headers',
        'X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version'
    )

    return res
}

// 中间件只会应用于以下路由。
export const config = {
    matcher: '<your-source-url(s)>',
}

你现在可以通过配置 matcher 来适配这段代码,它指定了你的来源可以访问的 source-urls。

3. Vercel 配置文件

假设你在 Vercel 上托管你的 Next.js 应用程序,你还可以在 Next.js 项目的根目录下添加一个 vercel.json 文件,并按照以下方式自定义它:

json 复制代码
// 类似于 next.config.js 方法,但使用不同的路径正则表达式语法(参见 vercel.json 文档)。

// https://vercel.com/docs/projects/project-configuration#headers

{
  "headers": [
    {

      "source": "<your-source-url(s)>",
      "headers": [
        { "key": "Access-Control-Allow-Credentials", "value": "true" },
        { "key": "Access-Control-Allow-Origin", "value": "<your-origin>" },
        { "key": "Access-Control-Allow-Methods", "value": "GET,DELETE,PATCH,POST,PUT" },
        { "key": "Access-Control-Allow-Headers", "value": "X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version" }
      ]
    }
  ]
}

针对多个端点调整 CORS 策略

目前,你只能为特定模式的来源(例如 api/:path*)追加 Headers。

但假设你需要为另一个特定来源或多个来源应用特定的 CORS Headers。

使用中间件允许多个来源:

javascript 复制代码
import { NextResponse } from "next/server";

// 所有允许的来源列表
const allowedOrigins = [
  'http://localhost:3000', 
  'https://example-1.com', 
  'https://example-2.com', 
  // ...
  'https://example-99.com', 
];

export function middleware(req) {
    // 检索当前响应
    const res = NextResponse.next()

    // 从传入请求中检索 HTTP "Origin" headers
    req.headers.get("origin")

    // 如果来源是允许的一个,
    // 将其添加到 'Access-Control-Allow-Origin' headers
    if (allowedOrigins.includes(origin)) {
      res.headers.append('Access-Control-Allow-Origin', origin);
    }

    // 将剩余的 CORS Headers 添加到响应中
    res.headers.append('Access-Control-Allow-Credentials', "true")
    res.headers.append('Access-Control-Allow-Methods', 'GET,DELETE,PATCH,POST,PUT')
    res.headers.append(
        'Access-Control-Allow-Headers',
        'X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version'
    )

    return res
}

// 中间件只会应用于以下路由。
export const config = {
    matcher: '<your-source(s)',
}

使用 vercel.jsonnext.config.js 为额外的特定来源:

javascript 复制代码
// next.config.js

/** @type {import('next').NextConfig} */
const nextConfig = {
    async headers() {
        return [
            {
                // 匹配所有 API 路径
                source: "/api/:path*",
                headers: [
                   // 为了简洁省略...
                ]
            },
            // 额外的特定来源:/api/special-data
            {
                source: "/api/special-data",
                headers: [
                    { key: "Access-Control-Allow-Credentials", value: "false" },
                    { key: "Access-Control-Allow-Origin", value: "https://example.com" },
                    { key: "Access-Control-Allow-Methods", value: "GET,DELETE,PATCH,POST,PUT" },
                    { key: "Access-Control-Allow-Headers", value: "Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date" },
                ]
            }
        ]
    }
}

module.exports = nextConfig

总结

CORS 是一种重要的安全机制,它保护你的网站免受跨来源请求的侵害。使用本文介绍的三种方法,就可以正确为你的 Next.js 应用提升安全策略了。

相关推荐
dy171714 小时前
element-plus表格默认展开有子的数据
前端·javascript·vue.js
2501_9159184118 小时前
Web 前端可视化开发工具对比 低代码平台、可视化搭建工具、前端可视化编辑器与在线可视化开发环境的实战分析
前端·低代码·ios·小程序·uni-app·编辑器·iphone
程序员的世界你不懂19 小时前
【Flask】测试平台开发,新增说明书编写和展示功能 第二十三篇
java·前端·数据库
索迪迈科技19 小时前
网络请求库——Axios库深度解析
前端·网络·vue.js·北京百思可瑞教育·百思可瑞教育
gnip19 小时前
JavaScript二叉树相关概念
前端
attitude.x20 小时前
PyTorch 动态图的灵活性与实用技巧
前端·人工智能·深度学习
β添砖java20 小时前
CSS3核心技术
前端·css·css3
空山新雨(大队长)20 小时前
HTML第八课:HTML4和HTML5的区别
前端·html·html5
猫头虎-前端技术21 小时前
浏览器兼容性问题全解:CSS 前缀、Grid/Flex 布局兼容方案与跨浏览器调试技巧
前端·css·node.js·bootstrap·ecmascript·css3·媒体