【问题标题】:Securely Passing UserID from ASP.Net to Javascript将用户 ID 从 ASP.Net 安全地传递到 Javascript
【发布时间】:2012-11-01 23:50:16
【问题描述】:

在我目前正在开发的应用程序中,我们使用 ASP.Net 表单身份验证来授予用户进一步访问该站点的权限。该站点面向移动用户,因此我们试图尽可能地脱离服务器,并利用 KnockoutJS 进行 Web 服务调用并加载数据,以便用户可以查看它。

现在 web 服务(使用 GET 方法的 REST 服务)需要用户名才能加载特定于该用户的数据。我在服务器端 (ASP.net) 上有这些信息,我可以轻松访问 User.Identity.Name 或直接访问表单身份验证 cookie 并提取信息。

我的问题是我需要从服务器获取用户名到客户端,以便可以进行服务调用。我已经考虑过安全地执行此操作,但到目前为止还一片空白。目前我将用户名作为 url 参数传递并使用 JavaScript 解析它,并检查 Page_Load 方法以验证 url 中的用户名与登录用户匹配。

我需要一种方法来安全地将用户名从 ASP.Net 传递到客户端 JavaScript,该用户名已使用表单对用户进行身份验证,以便我可以进行 REST Web 服务调用。

编辑:所以在谷歌搜索并与我的团队负责人会面后,我认为我们将使用类似于此示例的 OAuth 实现:

http://www.c-sharpcorner.com/UploadFile/surya_bg2000/secure-wcf-restful-service-using-oauth/

对于其他任何寻找相同答案的问题,我发现这个问题对理解 OAuth 非常有帮助:

What's the point of a timestamp in OAuth if a Nonce can only be used one time?

假设一切都正确实施,是否会更安全(完全安全、安全还是更不安全?)而不是通过如下所述的 ASP 标签传递生成的签名?

编辑 2:经过更多的审查和更多的搜索,我们最终决定了一个框架和方法来完成这项工作。事实证明 OAuth 不一定是这里的答案,这个问题:

But Seriously.... Example of ASP.NET WebAPI implementation including OAuth

在弄清楚如何进行这项工作方面也提供了很多帮助。我们最终要做的是生成签名并放入 javascript 并像这样进行调用。签名将是时间敏感的,并且每次用户加载页面时都会重新生成,非常像 OAuth,但我们没有实现完整的规范。

TL:DR 最终的解决方案是生成一个哈希签名并通过 ASP 服务器标记 将其放在页面上,并使用它来验证服务调用

【问题讨论】:

  • 服务是否与您的用户登录的站点位于同一服务器/域上?
  • 是的,它们都将驻留在同一个域中

标签: javascript asp.net forms authentication knockout.js


【解决方案1】:

如果您只想在客户端使用用户名,其他答案说明了如何执行此操作。
但正如您所说,这 IS 存在安全风险。有人可以修改客户端上的数据并冒充其他用户。

正确的做法:

  1. 用户成功登录后,会发出一个Guid,唯一标识该用户。
  2. Guid 是保存在客户端并传递给服务器的令牌不是用户名
  3. 所有 Web 服务都会收到 Guid 而不是用户名。
  4. 服务器有一个字典,可以将 Guid 转换为原始用户名。

另一个选项可以是encrypt 用户名并将加密 值传递给网络服务。网络服务需要解密该值才能获取用户名。

【讨论】:

  • 绝对是一个好建议,我的反问是:有没有办法在不修改现有网络服务的情况下做到这一点?
  • 好吧,如果您的 Web 服务收到 ONLY 用户名,并仅根据该用户名返回信息 - 那么您可能别无选择,因为这里存在严重的安全/设计缺陷。从好的方面来说,无论您选择使用 Guid 还是加密用户名 - 它仍然是一个字符串值,因此不会破坏 WSDL,您所要做的就是更改 Web 服务的内部逻辑
【解决方案2】:

通常,用户名由客户端提供。然后在服务器端对其进行验证(使用任何必要的身份验证,例如密码)。

如果它已在服务器端验证(在您的情况下,这必须来自 WCF Web 服务,因为 ASMX 不能很好地处理 REST),那么您可以确定它是正确的 - 而且您已经拥有客户端的用户名。

编辑: 正如 Knaģis 指出的那样,您可以使用 ASPX 标记来获取它,假设该页面是 ASPX 页面而不是 HTML。

【讨论】:

    【解决方案3】:

    最简单的方法是在您的页面中呈现此 javascript:

    <script type="text/javascript">
       window.UserID = '<%=HttpUtility.JavaScriptStringEncode(this.User.Identity.Name)%>';
    </script>
    

    现在你可以在你的 JS 中引用它了。

    但是,更重要的是,如果这个用户 id 不只是用作默认参数,而是用于验证用户,这是一个安全漏洞。通常,REST 服务也应该能够查看 User.Identity.Name 而不是将其作为参数接收。

    【讨论】:

    • 在服务器上加密,像你上面所说的那样将它传递给 JS,然后在 Web 服务中解密呢?您能否详细说明执行此类操作的安全性?
    • 是的,你可以用加密做类似的事情。但是 - 您应该确保加密的数据不会被重复使用 - 例如,还要加密时间戳,并在解密时检查时间戳是否在最后 X 分钟内。否则有人可能会窃取一次加密的用户名,然后继续使用它来伪造身份验证。
    • 感谢您的帮助,这是我们最终要使用的解决方案
    猜你喜欢
    • 2015-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-28
    • 1970-01-01
    • 2011-09-14
    相关资源
    最近更新 更多