如何在 .NET WCF 中保护 HTTP JSON Web 服务

Posted

技术标签:

【中文标题】如何在 .NET WCF 中保护 HTTP JSON Web 服务【英文标题】:How to secure HTTP JSON web service in .NET WCF 【发布时间】:2012-01-05 06:30:43 【问题描述】:

所以,我想保护一个 http json 网络服务。

我会有一堆系统用户,他们都有一个用户名和密码。 我只想在我的数据库中存储用户密码的随机加盐散列,以避免在数据库被泄露的情况下发现所有密码,以及盐(每个密码)以避免预先计算的彩虹表/字典攻击。

我一直在研究摘要式身份验证,因为它具有通过使用服务器向客户端提供的随机“nonce”防止重放攻击的好处,如下所示:

A1 = string.hashMD5 (username + ":" + realm + ":" + password)
A2 = string.hashMD5 (paramTable.method + ":" + paramTable.uri)
requestdigest = string.hashMD5 (A1 + ":" + nonce + ":" + A2)

但是,为了让服务器重新计算“requestdigest”,它必须知道“密码”,但我的服务器只能访问加盐哈希。

如果我没有使用盐,我可以像这样在客户端添加进一步的步骤(因为在客户端密码是已知的)-

HashedPword = string.hashMD5(password)
A1 = string.hashMD5 (username + ":" + realm + ":" + HashedPword)
A2 = string.hashMD5 (paramTable.method + ":" + paramTable.uri)
requestdigest = string.hashMD5 (A1 + ":" + nonce + ":" + A2)

然后在服务器端,我可以从数据库中检索哈希密码以执行重新计算。

唉,客户也需要知道盐才能正确地做到这一点,例如

HashedSaltedPword = string.hashMD5(password+salt)
A1 = string.hashMD5 (username + ":" + realm + ":" + HashedSaltedPword)
A2 = string.hashMD5 (paramTable.method + ":" + paramTable.uri)
requestdigest = string.hashMD5 (A1 + ":" + nonce + ":" + A2)

这样一来,在给定用户名的情况下,可能会暴露一个返回 salt 的 Web 服务函数,从而在没有身份验证的情况下将 salt 传输给客户端。 但随后任何人都可以使用盐。

我想知道的是,如果分发盐是一个问题。 因为,如果没有存储在数据库中的散列,salt 本身是无用的,如果数据库被破坏,那么攻击者无论如何都可以访问散列和盐。 然后,如果我免费赠送盐,那么我也可以将用户名本身用作盐,因为每个用户都是唯一的 - 因此我什至不需要公开网络服务调用首先发现盐。

你们怎么看?暴露盐或具有已知的盐化机制是否重要? 还有其他想法吗?

我并不真正担心消化身份验证的缺点 - 即客户端不知道它是否正在与“真实”服务器通信。因为,使用这种方法不会暴露客户的密码,而且我不会通过此链接向客户询问任何机密信息,例如信用卡。 IE。我想要保护的东西位于我的服务器上,服务器不会向客户端询问他们的任何安全信息。

编辑: 嗯,实际上我刚刚阅读了这个链接Salt, passwords and security,它基本上向我证实了知道盐并不重要。 所以我正在考虑实现某种哈希,例如:

HashedSaltedPword = string.hashMD5(password+username+siteWideSaltExistingOnlyInCode)

添加站点范围的盐是为了以防有人为常用用户名创建了彩虹表。 这种方法看起来安全吗?

【问题讨论】:

您的问题与 JSON 没有太大关系,是吗?我认为它可能有点长而沉重。您似乎真的在问“当我只存储加密密码时如何使用摘要式身份验证?” 【参考方案1】:

您必须选择您希望如何传输密码。您是否只想将其从客户端散列传输到服务器端?在这种情况下,服务器必须存储密码,否则它将无法重新计算哈希。您希望服务器不存储密码吗?在这种情况下,您必须以纯文本形式传输密码,以便服务器可以计算哈希值并将其与存储的哈希值进行比较。

前一种情况需要在数据库中存储密码,如果你想保护它们,你应该使用一些数据库/应用程序级别的加密。后一种情况需要安全传输(HTTPS、*** 等),因为密码以可读形式传输。

【讨论】:

其实这并不需要在数据库中存储密码 - HashedSaltedPword = string.hashMD5(password+username+siteWideSaltExistingOnlyInCode),因为在初始注册时,这个 HashedSaltedPword 就是我们存储到数据库中的内容。所以在客户端,不是将明文密码放入摘要认证中,而是先在客户端计算HashedSaltedPword,然后将其代替密码放入摘要认证函数中 所以如果有人知道哈希,他根本不需要知道密码?是的,它可以工作,但您再次需要安全传输。

以上是关于如何在 .NET WCF 中保护 HTTP JSON Web 服务的主要内容,如果未能解决你的问题,请参考以下文章

如何配置net.tcp 的WCF服务

如何使用 AWS 身份验证保护我的 wcf 服务

如何从 .NET Core 3.1 中的 F# 访问 WCF 服务?

Azure 使用 Azure 函数保护 WCF asmx

如何解决 C# IIS 托管的 WCF NET TCP 服务超时问题

.Net Core 中的 Http 绑定使用带有 wcf 引用的库项目