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)之间传递请求。通过代理服务器:
- 浏览器向代理服务器发起请求。
- 代理服务器再向目标服务器发起请求,并返回结果。
在这种情况下,代理服务器的作用就是绕过 CORS 的限制,因为 CORS 规则只对客户端(浏览器)生效,而服务器端的请求不受这个限制。
如何用 NextJS 解决 CORS 问题?
-
客户端直接请求(会遇到 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); }; -
通过代理服务器解决(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; // 仅在服务器端可用
总结
通过这次实践,学到了以下几点:
- CORS 是浏览器的一项安全机制,可以通过代理服务器解决。
- API 密钥应该保存在服务器端,避免暴露到客户端代码中。
- 使用环境变量时,谨慎区分
NEXT_PUBLIC_前缀的变量和仅用于服务器端的变量。
这个经验不仅解决了跨域问题,还提升了 API 调用的安全性,值得每位前端开发者学习!