Next.js 下,如何安全地设置 CORS 和 API 密钥

445 阅读3分钟

NextJS 能让前端开发者更简单地处理 跨域资源共享(CORS)API 密钥 安全问题。


什么是 CORS?

CORS(跨域资源共享)是浏览器的一项安全机制,用于保护用户免受恶意网站的攻击。如果一个网站试图访问其他域名上的资源,浏览器会检查服务器是否允许跨域请求。

  • 跨域示例:

    • 你的前端网站地址是 https://your-frontend.com
    • 你需要从 https://external-api.com 获取数据。
    • 如果 https://external-api.com 的服务器没有返回正确的 CORS 允许头信息(如 Access-Control-Allow-Origin: https://your-frontend.com),浏览器会直接阻止请求,并报错。

什么是代理服务器?

代理服务器 是一个“中间人”,负责在客户端(如浏览器)和目标服务器(如外部 API)之间传递请求。通过代理服务器:

  1. 浏览器向代理服务器发起请求。
  2. 代理服务器再向目标服务器发起请求,并返回结果。

在这种情况下,代理服务器的作用就是绕过 CORS 的限制,因为 CORS 规则只对客户端(浏览器)生效,而服务器端的请求不受这个限制。


如何用 NextJS 解决 CORS 问题?

  1. 客户端直接请求(会遇到 CORS 问题):

    const fetchData = async () => {
      const response = await fetch('https://external-api.com/endpoint', {
        method: 'POST',
        headers: {
          Authorization: 'Bearer API_KEY',
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({ data: 'example' }),
      });
      const result = await response.json();
      console.log(result);
    };
    
  2. 通过代理服务器解决(NextJS 中的 API 路由):pages/api/proxy.js 中添加代理逻辑:

    export default async function handler(req, res) {
      const response = await fetch('https://external-api.com/endpoint', {
        method: 'POST',
        headers: {
          Authorization: `Bearer ${process.env.API_KEY}`,
          'Content-Type': 'application/json',
        },
        body: JSON.stringify(req.body),
      });
      const result = await response.json();
      res.status(response.status).json(result);
    }
    

    客户端调用方式变为:

    const fetchData = async () => {
      const response = await fetch('/api/proxy', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({ data: 'example' }),
      });
      const result = await response.json();
      console.log(result);
    };
    

这样,浏览器只会请求代理服务器(/api/proxy),不会直接请求外部 API,自然也就没有 CORS 问题。


如何保护 API 密钥?

之前,API 密钥被写在客户端代码中,可能会暴露在浏览器的网络请求里。当通过代理服务器处理请求后,API 密钥只在服务器端使用,完全避免了暴露风险。


环境变量和安全性

在 NextJS 中:

  • NEXT_PUBLIC_ 前缀的变量 是给客户端使用的,会被打包到最终的前端代码里,可能会暴露。
  • 未带前缀的变量 仅限于服务器端代码,能更好地保护敏感信息。

错误示例:

const API_KEY = process.env.NEXT_PUBLIC_API_KEY; // 可能暴露在客户端

正确示例:

const API_KEY = process.env.API_KEY; // 仅在服务器端可用

总结

通过这次实践,学到了以下几点:

  1. CORS 是浏览器的一项安全机制,可以通过代理服务器解决。
  2. API 密钥应该保存在服务器端,避免暴露到客户端代码中。
  3. 使用环境变量时,谨慎区分 NEXT_PUBLIC_ 前缀的变量和仅用于服务器端的变量。

这个经验不仅解决了跨域问题,还提升了 API 调用的安全性,值得每位前端开发者学习!