保护我将在客户端使用的REST服务,以及其他人使用的服务

时间:2011-10-21 13:24:14

标签: javascript wcf api rest wcf-web-api

假设我已经顺利创建了我的REST服务,并且我正在返回json结果。

我还为我的用户实现了API密钥,以便为我的服务进行通信。

然后公司A开始使用我的服务,我给了他们一个API密钥。

然后他们为网桥创建了HttpHandler(我不确定这里的术语是什么)以便不公开API密钥(我也不确定它是正确的方式)

例如,假设我的服务网址如下:

  

www.myservice.com/service?apikey= {key_comes_here}

A公司正在客户端使用此服务,如下所示:

  

www.companyA.com/services/service1.ashx

然后他们开始在客户端使用它。

公司A在这里保护了api密钥。没关系。

但这里还有另一个问题。其他人仍然可以抓住www.companyA.com/services/service1.ashx网址并开始使用我的服务。

阻止他人这样做的方法是什么?

为了记录,我正在使用WCF Web API来创建我的REST服务。

更新:

公司A的HttpHandler(第二个链接)仅查看主机标头,以查看它是否来自www.companyA.com。但我猜是可以伪造的。

更新2:

是否有任何已知的方法为url实现令牌。例如,假设www.companyA.com/services/service1.ashx将携带表示TOKEN的查询字符串参数,以便HttpHandler检查请求是否正确。

但我猜这里有很多事情要考虑。

3 个答案:

答案 0 :(得分:1)

您所描述的内容通常被称为“代理” - 公司A的公共页面可供任何人使用,并且在幕后,它可以对您的系统进行正确的调用。应用程序使用代理来绕过安全性并不少见 - 例如,同源策略意味着您的javascript无法对Amazon进行Ajax调用 - 但如果您在自己的系统上代理它,那么可以绕过这个。

我真的不能想出一种防止这种情况的技术方法;一旦他们从您的服务中提取数据,他们就可以随意使用这些数据。当然,你有合法的选择;您可以使其成为不允许代理的服务条款,如果不遵守,则提取其API密钥。但最有可能的是,如果您尚未将其纳入服务条款,则必须等待续订订购服务。

据推测,如果他们向您的服务发出服务器端HTTP请求,那些请求都来自同一个IP地址,因此您可以阻止该地址。你可能想先告诉他们,如果他们愿意,他们当然可以解决这个问题。

答案 1 :(得分:1)

您始终可以要求客户端使用HTTP Basic Auth或某些自定义方案进行身份验证。如果您的客户要求用户登录,您至少可以限制公众获取www.companyA.com/services/service1.ashx网址,因为他们需要登录才能找到相关信息。

如果您还试图保护URL免受合法访问官方客户端的人的意外使用,则会变得更加困难。您可以尝试定期更改服务密码,并随之更新客户端。这样刷新浏览器中的客户端就会获取新密码,但是构建自定义代码的任何人都会过时。当然,一个真正坚定的用户可以编写代码来在客户端JS以编程方式更改密码,但是你至少可以防止偶然的侵权者。

关于您在更新2中提到的URL令牌想法,它可以像这样工作。想象一下,每个月www.companyA.com/services/service1.ashx网址都需要新的令牌才能运作,例如www.companyA.com/services/service1.ashx?token=January。一旦二月,'一月'将停止工作。服务器必须知道只接受当前月份,客户端必须知道发送令牌(在客户端网页从浏览器中的服务器加载时确定)

(所有伪代码,因为我不知道C#以及你将使用哪个JS框架)

服务器端代码:

if (request.urlVars.token == Date.now.month) then
   render "This is the real data: [2,5,3,5,3]"
else
   render "401 Unauthorized"

客户端代码(由您的服务提供的动态版本) www.companyA.com/client/myajaxcode.js.asp

var dataUrl = 'www.companyA.com/services/service1.ashx?token=' + <%= Date.now.month %>
// below is JS code that does ajax call using dataUrl
...

所以现在我们的服务代码只接受当前月份作为令牌,并且当您在浏览器中刷新时获取最新令牌(动态设置为当前月份)的客户端代码。由于这个方案真的可以预测并且可能被黑客入侵,剩下的步骤是对令牌进行盐析哈希,因此没有人可以猜出它将会是什么。

if (request.urlVars.token == mySaltedHashMethod(Date.now.month)) then

var dataUrl = 'www.companyA.com/services/service1.ashx?token=' + <%= mySaltedHashMethod(Date.now.month) %>

哪会留下像www.companyA.com/services/service1.ashx?token=gy4dc8dgf3f这样的网址,并且会每月更改一次令牌。

你可能想要比每个月更快到期,你可以使用纪元时而不是月来。

我有兴趣看看那里有人用某种加密的客户端代码解决了这个问题!

答案 2 :(得分:0)

A公司暴露了第二条链接,我觉得你不能做太多。据我了解,您只能检查收到的请求是否来自A公司。

但是,发给www.companyA.com/的每个请求都无法与A公司的原始请求区分开来。他们允许的每个人都使用他们的推荐人作为伪装。