使用客户端令牌

时间:2016-12-06 08:35:23

标签: javascript node.js rest security

我有一个node.js REST API,我希望将POST / PUT / DELETE调用限制为预定义的"来源" (我不拥有代码的Web应用程序)。

我认为实现这一目标的唯一方法是在客户端放置一个令牌(比如JS文件中的Google Analytics),但我不知道如何确保这一点,因为令牌会可以在静态文件中访问。

我应该采用什么策略? JWT和OAuth2似乎没有显示,因为它需要第一次用户身份验证,但我要验证的不是用户而是webapps。

3 个答案:

答案 0 :(得分:0)

你的问题有点不清楚。您可能意味着(a)您希望强烈鼓励用户使用该应用程序并防止其他代码恶意让您的用户执行操作,或者(b)您希望绝对阻止您的用户使用其他代码访问你的服务器。

第一种选择是可能的,而且确实是一个非常好的主意。第二种是不可能的,基于互联网的运作方式。

首先,不可能。从本质上讲,客户端代码可以让您的客户更轻松。真正的工作总是在服务器端完成 - 即使这仅仅意味着验证数据并将其存储在数据库中。您的客户端始终能够看到他们发送的所有HTTP请求:这就是HTTP的工作方式。您无法隐藏它们的信息。即使您动态生成令牌(见下文),也无法阻止它们在其他地方使用它们。他们总是可以构建自定义HTTP请求,这意味着最终他们可以(如果他们真的真的想要)完全放弃您的应用程序。将您的客户端代码视为仅仅使他们更容易执行HTTP请求并放弃任何阻止他们“做错”的想法!

更好的选择是CSRF保护,它为您的服务器和客户端提供最好的保护。这意味着,当客户端首次登录并在每次请求发送时,通过查找或解密来向客户端发送生成的令牌。这是JWT的基础,它是一个相当古老的验证系统的美丽实现。

答案 1 :(得分:0)

最后,您的API是公开的,因为任何随机网站访问者都必须能够与API进行交互。即使您使用令牌来限制访问权限,根据定义,这些令牌也必须是公开的。即使定期过期和续订令牌(例如通过后端API,或通过包含随机数算法)也不会有帮助,因为这些新令牌将再次在第三方网站上公开显示,任何人都可以获取之一。

CSRF保护可以帮助一点以避免浏览器中的跨网站滥用,但最终没有意义,以防止某人编写API刮刀等。

您可以做的最好的事情是使用令牌来识别您授予访问权限的各个网站所有者,警惕地监控您的API使用情况,当您认为自己被滥用时使令牌无效,并与网站所有者联系以确保其令牌的安全不知怎的更好(他们会有同样的问题,但至少你有人责备<咳嗽咳嗽)。

答案 2 :(得分:-1)

您可以使用hmac来保护这个: 每个客户都有一对独特的关键公共/私人(例如“公共”和“私人”)。

当客户端发送请求时,他必须用他的私钥发送一个nonce +他的用户公钥+ nonce +公钥的hmac。

当服务器处理请求时,服务器根据其公钥检索客户端,获取用户的密钥,然后验证签名。

Client, sample call on /api

var nonce = "randomstring";
var pk    = "aaa";
var sk    = "bbb";

var string = "pk="+pk+"&nonce="+nonce;

var crypto = require('crypto');
var hmac   = crypto.createHmac('sha512', sk).update(string).digest('hex');

// send this payload in your request in get, put, post, ....
var payload = string+"&hmac="+hmac; 

request.post({uri:"website.com/api?"+payload}, ....

并且

Server side, security check

var nonce = req.query.nonce;
var pk    = req.query.pk;
var hmac  = req.query.hmac;

// retrieve user and his sk according to pk
var sk = getUser(pk).sk

// rebuild payload string
var string = "pk="+pk+"&nonce="+nonce;

var crypto = require('crypto');
var hmac_check   = crypto.createHmac('sha512', sk).update(string).digest('hex');

if(hmac_check === hmac) { // request valid }else{ // invalid request }