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 应用提升安全策略了。

相关推荐
阿伟来咯~36 分钟前
记录学习react的一些内容
javascript·学习·react.js
吕彬-前端41 分钟前
使用vite+react+ts+Ant Design开发后台管理项目(五)
前端·javascript·react.js
学前端的小朱44 分钟前
Redux的简介及其在React中的应用
前端·javascript·react.js·redux·store
guai_guai_guai1 小时前
uniapp
前端·javascript·vue.js·uni-app
bysking2 小时前
【前端-组件】定义行分组的表格表单实现-bysking
前端·react.js
王哲晓2 小时前
第三十章 章节练习商品列表组件封装
前端·javascript·vue.js
fg_4112 小时前
无网络安装ionic和运行
前端·npm
理想不理想v2 小时前
‌Vue 3相比Vue 2的主要改进‌?
前端·javascript·vue.js·面试
酷酷的阿云2 小时前
不用ECharts!从0到1徒手撸一个Vue3柱状图
前端·javascript·vue.js
微信:137971205872 小时前
web端手机录音
前端