Next.js 默认情况下是同站点来源,但我仍然可以访问它

Mar*_* Dz 7 next.js

我想知道如何保护我的 api 路由。文档说,api 路由默认是同站点源。

API 路由不指定 CORS 标头,这意味着它们仅在默认情况下是同源的。您可以通过使用 cors 中间件包装请求处理程序来自定义此类行为。 Next.js 文档

但是,如果我使用像 Postman 这样的请求工具,我总是可以调用它并获取结果:

// Next.js API route support: https://nextjs.org/docs/api-routes/introduction

export default (req, res) => {
  res.status(200).json({ name: 'John Doe' })
}
Run Code Online (Sandbox Code Playgroud)

这怎么可能?我只想限制对我的应用程序的访问。

brc*_*-dd 4

您问题的第一部分的答案是:CORS with Postman

对于第二部分,我利用短期访问令牌的概念编写了一个非常小的代码(太简化了)。

// utils/protector.js

let oldToken, newToken;
const checkToken = ({ headers: { 'x-access-token': token } }) =>
  token && (token === oldToken || token === newToken);

const refreshToken = () => {
  oldToken = newToken;
  newToken = Math.random().toString(36).substr(2);
  setTimeout(refreshToken, 3 * 60 * 60 * 1000); // each token is valid for 3 hrs
};
refreshToken();

export { checkToken, newToken as accessToken };
Run Code Online (Sandbox Code Playgroud)
// api/user.js

import { checkToken } from '../../utils/protector';

const handler = (req, res) => {
  // just add this line to the top of your handler
  if (!checkToken(req)) return res.status(403).send();

  // your API logic here...
  res.status(200).json({ name: 'John Doe' });
};

export default handler;
Run Code Online (Sandbox Code Playgroud)

现在在页面中您想要使用受保护的 API:

// index.js

import { useState, useEffect } from 'react';

import { accessToken } from '../utils/protector';

const Home = ({ accessToken }) => {
  const [user, setUser] = useState('Guest');

  useEffect(() => {
    // this will be called from the client
    fetch('/api/user', { headers: { 'x-access-token': accessToken } })
      .then((response) => response.json())
      .then((data) => setUser(data.name));

    return () => {};
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  return <div>Hello {user}!</div>;
};

const getServerSideProps = async () => {
  return { props: { accessToken } };
};

export default Home;
export { getServerSideProps };
Run Code Online (Sandbox Code Playgroud)

使用受保护路由的任何页面都应该在服务器端呈现,否则保护器代码将与客户端捆绑在一起并在浏览器中执行,从而导致服务器端(API)和客户端产生不同的令牌。


oldToken和的概念newToken可能显得相当不清楚。认为:

  • 用户于 11:59 访问您的网站。

  • 您的令牌会在 00:00 刷新。

  • 他们在 12:01 触发了 API 调用。

  • 现在,如果没有oldToken,则newToken会在调用之前发生变化,并且响应将是 403 Forbidden Error。


我假设用户在您的页面上执行调用受保护 API 的操作之前只需要不到 3 小时的时间。

超时设置为 3 小时,即使令牌的有效时间是其时间的两倍,因为如果超时为一半(即 1.5 小时)并且(上述)用户在 01:31 触发 API 调用。然后oldTokennewToken, 和newToken是较新的,两者都不会与用户拥有的相匹配。

因此,为了保证收到的令牌至少在 3 小时内有效,总生存时间是两倍。令牌的有效期可能为 6 小时(例如对于 12:00 访问该网站的用户)。