2

我有一个使用 Node.js 和 Express 4.x 构建的 Web 应用程序,其中一个典型的页面如下所示:

...
<script type="text/javascript" src="jquery-3.3.1.min.js"></script>
<script type="text/javascript" src="d3-5.4.0.min.js"></script>
<script type="text/javascript">
    $(loadData); // When the page is fully loaded, call loadData()
    function loadData() {
        d3.json('/data/purchases').then(generateCharts);
    }
    function generateCharts(data) { }
</script>
...

它只是调用d3.json()从服务器读取数据,然后用它们生成一些图表。

与服务器通信的方式d3.json()是使用对指定 URL 的 GET 请求,在示例中是 /data/purchases。如果有人在浏览器中键入相同的 URL,他们显然会得到与 JSON 数据相同的响应。这就是我想要阻止的。

有什么方法可以检查请求是否来自d3.json()电话?

我想X-Requested-With用 Express 属性检查标题req.xhr,但它设置为 false。显然d3-fetch不使用 XMLHttpRequest 来加载数据,而是使用新的 Fetch API

我也尝试过req.is('application/json')......但它返回null。

还有什么我可以尝试的吗?

PS:我已经有一个简单的授权系统,它检查当前用户是否应该有权访问任何请求的 URL,包括页面和 API 调用。但它需要一些额外的配置数据存储在我的数据库中,使应用程序更难维护。因此,鉴于我们实际上没有任何敏感数据,我想我可以放弃对 API 调用的授权检查,而只允许通过d3.json()而不是手动进行它们。相反,我可以完全允许它们......我只是不想:),这提供了一个了解更多关于 Express 和 D3.js 的机会。

4

1 回答 1

1

d3.json() 允许将 init 参数传递给底层的 Fetch 调用。除其他外,这可用于定义自定义标头

const initParams = {
    headers: new Headers({
        "MyVeryOwnHeader": "Hooray!"
    })
};

d3.json('/data/purchases', initParams).then(generateCharts);

然后可以在 Express 的 routes.js 文件中检查服务器端:

if (req.get('MyVeryOwnHeader') === 'Hooray!') {
    // Valid API call made from d3.json, not by the user directly typing the URL
}

这就是基础;您可以根据需要将其复杂化。例如,您可以为每个请求的页面生成一个随机令牌(或随机数)而不是静态值,并将其存储在会话变量中,以便稍后在验证下一个 API 调用时检查该值。唯一的问题是用户同时浏览多个标签:这可能会导致某些页面无法加载必要数据的竞争条件。

当然,如果用户愿意,他们仍然可以检查代码,找出最后一个令牌,然后生成对 API 的虚假调用,包括自定义标头。这根本不是为了提供任何安全性,只是为了阻止直接访问数据。

于 2019-08-13T07:01:42.600 回答