如何在不重写所有路由的情况下禁用 Express 中单个路由的 CORS?

Posted

技术标签:

【中文标题】如何在不重写所有路由的情况下禁用 Express 中单个路由的 CORS?【英文标题】:How can I disable CORS for a single route in Express without rewriting all of my routes? 【发布时间】:2020-10-11 17:05:04 【问题描述】:

TLDR:在示例中,我只是想让/users/delete 不能被我的 React 应用程序之外的任何东西调用。

我的应用程序的后端 API 有一堆路由,它们使用 Express:

即。 server.js

app.get('/invoices/read', async (req, res) => 
    // gather data from db
    res.json(...data)
)

我已经像这样全局启用了 cors:

server.js

app.use(function(req, res, next) 
  res.header('Access-Control-Allow-Origin', '*');
  res.header(
    'Access-Control-Allow-Headers',
    'Origin, X-Requested-With, Content-Type, Accept'
  );
  next();
);

所以,我的问题是,如何为这样的单个路由禁用 CORS

app.post('/users/delete', async (req, res) => 
    // delete user out of database
    res.sendStatus(200)
)

无需将我的所有路线都重写为这样的:

var cors = require('cors');

app.get('/invoices/read', cors(), async (req, res) => 
    // gather data from db
    res.json(...data)
)

这样用户就不能只使用任意 ID 向/users/delete 发出 POST 请求以尝试将用户从我的系统中删除?

我需要只在我的标头中包含原点还是需要为该路由禁用 CORS?

过去,我在使用 Access-Control-Allow-Origin 标头获取源字符串时遇到了麻烦。

【问题讨论】:

只需在启用 CORS 的中间件之前放置一条路由。然后,在为该路由提供服务时,CORS 标头将不存在。 【参考方案1】:

仅在您要“禁用”它的路由上覆盖标头:

res.set('Access-Control-Allow-Origin', 'alloweddomain.com')

如果您需要允许多个域,您可以列出允许的域并检查源是否包含在其中:

const allowedDomains = ['allowedomain1.com', 'alloweddomain2.com'];
const origin = req.get('origin');

if (allowedDomains.includes(origin)) 
  res.set('Access-Control-Allow-Origin', origin);

【讨论】:

并且我可以通过向以空格分隔的字符串提供多个域来包含多个域?【参考方案2】:

我发现的另一个解决方案:

在全局调用app.use(cors())时,可以添加preflightContinue: true选项,这应该允许特定页面上的后续中间件覆盖它。

在***配置中

  app.use(
    cors(
      origin: 'http://localhost:9001',
      // Allow follow-up middleware to override this CORS for options
      preflightContinue: true,
    ),
  );

在我的具体路线声明中

router.options('/myRoute', cors(myRouteOptions));
router.post(
  '/myRoute',
  cors(myRouteOptions),
  async (req, res) => 
    // ...
  ,
);

【讨论】:

【参考方案3】:

使用 Express 路由器和cors 模块:

// Define the router 
const v1 = express.Router();

// Initiate express app
const api = express();

 const corsOptions = 
    origin: '*',
    methods: [],
    allowedHeaders: [],
    exposedHeaders: [],
    credentials: true
;

// Define subroutes here 
v1.get('/list', (req, res) =>  // action implementation here)

// Define cors per route 
v1.all('/list', cors(corsOptions));

// Add the router to express  
api.use('/', v1);

或者使用 cors 中间件

v1.get('/list',  cors(corsOptions), (req, res) =>  // action implementation here)

两者都应该工作,我希望这会有所帮助。

【讨论】:

如果我想重写所有路由,这会起作用,但是现在,在我的中间件中定义了数百条路由,我很难重写所有路由,因为其中一些实际上是已经包含中间件。 @Felipe 的回答提供了一种仅对单个路由禁用 CORS 的方法。 TLDR:谢谢,以后我会使用这种方法(向路由提供 CORS)。 我还没有测试过,所以我仍然愿意接受建议。

以上是关于如何在不重写所有路由的情况下禁用 Express 中单个路由的 CORS?的主要内容,如果未能解决你的问题,请参考以下文章

如何在不完成 Bootstrap 中的一个步骤的情况下禁用进入下一步?

WPF:如何在不禁用箭头键导航的情况下禁用选项卡导航?

如何在不卸载powershell的情况下,有效禁用/启用powershel

如何在不使用 each() 的情况下重写此函数? [复制]

如何在不使项目变灰的情况下禁用 UITabBarItem

如何在不禁用突出显示的情况下禁用合适的触摸行