Node JS:只允许服务器端调用我的 api

Posted

技术标签:

【中文标题】Node JS:只允许服务器端调用我的 api【英文标题】:Node JS : Allow only server side calls to my api 【发布时间】:2019-02-15 20:42:59 【问题描述】:

我一直在绞尽脑汁寻找一个简单的解决方案。 可以说,我的 Node JS 应用程序中有 10 个 API 端点。

我已经允许其中 3 个是公开的,其余 4 个具有基于 JWT 的身份验证

现在我还有 3 个路由,它们没有 JWT,我只需要允许服务器端调用。没有浏览器或 curl 或邮递员,应该能够调用它们。如何从请求对象中识别它来自服务器?

或者换句话说,如何拒绝对我的 api 的所有跨源调用?由于服务器端不属于 CORS,它们应该过滤

----- 编辑-----

我最近遇到了一个使用 User Agent 标头来阻止服务器端调用的服务。 我可以为我的服务强制执行用户代理标头并确保标头没有浏览器代理。这很容易被欺骗,但作为一个理论上的解决方案,nodejs 拦截器会丢弃用户代理引用浏览器代理的请求吗?

【问题讨论】:

服务器是否在您的控制之下?如果是这样,请使用某种形式的身份验证来识别它们。 基本上,这将是一个令牌解密服务:虽然使用公钥其他微服务可以验证 JWT 签名,但其中一些可能需要对有效负载进行解密。我想将此解密服务公开给一组非常特定的服务器。我的想法是在 DMZ 环境中托管这些服务器,但由于登录/令牌生成请求,UAA 也必须具有公共端点 你使用的是 docker swarm 还是 kubernetes? 我正在寻找可扩展的解决方案。现在,它托管在我本地的私人服务器中 【参考方案1】:

您可以使用express-ipfilter 包并将其仅应用于您想要保护的某些路由:

const express = require('express'),
      ipfilter = require('express-ipfilter').IpFilter;

// Whitelist the following IPs
const ips = ['127.0.0.1'];

// Create the route
app.get("/securePath", ipfilter(ips, mode: 'allow'), (req, res) => 
  // only requests from 127.0.0.1 (localhost/loopback) can get here
);

app.get("/openPath", (req, res) => 
  // all requests can get here
);

app.listen(3000);

如果您在代理后面使用 Node,您可能需要配置代理以设置带有实际 IP 的标头,然后将 ipfilter 函数传递给 detectIp 属性中的函数到第二个参数。

假设你正在使用 nginx 并已将其配置为通过 x-Real-IP 标头发送原始 IP,你可以将此函数传递给 ipfilter

const express = require('express'),
  ipfilter = require('express-ipfilter').IpFilter,
  ips = ['127.0.0.1'];

app.get("/securePath", ipfilter(ips, mode: 'allow', detectIp: getIp), (req, res) => 
  // only requests from 127.0.0.1 (localhost/loopback) that go through the proxy can get here.
);

app.get("/openPath", (req, res) => 
  // all requests can get here
);

app.listen(3000);

function getIp(req)  return req.headers["X-Real-IP"] 

【讨论】:

我之前已经成功使用过ip白名单。但是有没有其他方法,我们可以识别服务器与客户端的请求?可以说,我还没有调用服务器的 IP 范围,或者它们有动态 IP 范围 我不知道,没有。您可以使用动态 IP,您可以向 ipfilter 传递一个函数而不是 ips 数组 好的,我一定会检查的。 我的问题的第二部分怎么样:如何阻止所有来源访问特定端点?像 - “Access-Control-Allow-Origin” : null ?? 使用这个你可以指定只有运行脚本的服务器(即 127.0.0.1)可以访问路由,进而阻止所有其他源访问路由【参考方案2】:

对于从客户端获得 JWT 身份验证的路由,您应该使用类似的身份验证/授权。

这意味着调用者服务还应使用 JWT 令牌进行身份验证,具有特殊的 service 或类似的 role 或类似的东西(这 100% 取决于您选择哪种约定)。该令牌应由调用者签名并由接收微服务验证。

此解决方案的优点是它不依赖于基础架构,无论服务部署在哪里,它的工作原理都是一样的。

【讨论】:

以上是关于Node JS:只允许服务器端调用我的 api的主要内容,如果未能解决你的问题,请参考以下文章

如何设计我的 Node.js API,以便我也可以从服务器端使用它?

如何只允许从某些IP地址访问API

Node.js — 需要睡眠

Firebase Admin SDK - 与Node.JS相比,Java版本缺乏什么?

如何从 Node.js/Express 服务器调用 GraphQL API?

使用 Node.js 构建 API 网关