【问题标题】:Protecting my REST service, which I will use on the client side, from others to use保护我将在客户端使用的 REST 服务,使其不被其他人使用
【发布时间】:2011-10-21 23:13:18
【问题描述】:

假设我已经顺利地创建了我的 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 url 并开始使用我的服务。

有什么办法阻止别人这样做?

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

更新:

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

更新 2:

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

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

【问题讨论】:

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


    【解决方案1】:

    您总是可以要求客户端进行身份验证,使用HTTP Basic Auth 或一些自定义方案。如果您的客户要求用户登录,您至少可以限制公众获取www.companyA.com/services/service1.ashx URL,因为他们需要登录才能了解它。

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

    关于你在更新 2 中提到的 URL 令牌想法,它可以像这样工作。想象一下,每个月,www.companyA.com/services/service1.ashx URL 都需要一个新的令牌才能工作,例如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 这样的 URL,并且每个月都会更改令牌。

    您可能还希望比每个月都更快地到期,您可以使用纪元小时而不是月份来完成我的操作。

    我很想看看是否有人用某种加密的客户端代码解决了这个问题!

    【讨论】:

    • 目前我只看了第一段,我想说不,a公司的用户会匿名访问网站
    • 您的更新 2(在 url 中使用自定义令牌)与我上面提到的“更改密码”的概念相同,即为那些未经许可使用该服务的人提供移动目标。在这种情况下,您必须在一段时间后使令牌过期,因为您的 JS 调用的 url 很容易被发现。您的官方客户必须在新令牌更改时获取它的更新。这里的弱点是如果有人编写代码来破解您的客户端代码,因为它是 javascript,因此可以进行检查。以某种方式加密相关的 JS 代码会造成混淆。
    • 您的解决方案听起来很合乎逻辑,但我无法想象如何实现它。你能给我提供任何关于 C# 的示例代码来实现这个吗?或者您知道有关此主题的任何资源吗?
    【解决方案2】:

    您所描述的内容通常被称为“代理”——公司 A 的公共页面可供任何人使用,并且在幕后,它会正确调用您的系统。应用程序使用代理来绕过安全性的情况并不少见——例如,同源策略意味着你的 javascript 不能对亚马逊等进行 Ajax 调用——但如果你在自己的系统上代理它,你可以解决这个问题。

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

    大概如果他们向您的服务发出服务器端 HTTP 请求,这些请求都来自同一个 IP 地址,因此您可以阻止该地址。您可能想先告诉他们,如果他们愿意,他们当然可以绕过。

    【讨论】:

    • 感谢您的详细回答。以上两个角色暂时都是虚构的。所以,我在这里为双方考虑。你最后一段说的太对了。但目前还没有确定的解决方案。我可以让它变得更难,但并非不可能。
    【解决方案3】:

    对于A公司公开的第二个链接,我认为您无能为力。据我了解,您只能检查传入的请求是否来自A公司。

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

    【讨论】:

    • 是的,A 公司的 HttpHandler(第二个链接)只查看主机标头以查看它是否来自 www.companyA.com。但我猜很容易伪造。
    猜你喜欢
    • 1970-01-01
    • 2010-12-21
    • 1970-01-01
    • 1970-01-01
    • 2016-03-27
    • 2017-04-20
    • 2017-03-31
    • 2020-09-05
    • 2023-03-22
    相关资源
    最近更新 更多