我刚刚开始在 .NET 中开发我的第一个 REST API。由于它将是无状态的,我将使用 token 进行身份验证:
基本思想(System.Security.Cryptography):
- AES 加密 + HMACSHA256 完整性
- token 数据将包含具有属性的对象:用户名、发行日期和超时
- 数据库将保存用户名、哈希密码和 HMAC 哈希
登录:
- 检查凭据是否有效(用户名,将散列密码与数据库值进行比较)
- 如果为真,加密数据对象
- 在生成的 token 上使用 HMAC 并将其存储到数据库
- 将 token (无 HMAC)返回给用户(cookie/字符串)
请求需要身份验证的方法:
- 用户在每个请求中发送 token
- token 已解密
- 如果过期了,报错
- 如果没有过期,使用 HMAC 并将用户名 + 生成的哈希值与数据库值进行比较
- 如果数据库检查有效,则用户通过身份验证
在我看来,这种方法有以下优点:
- 即使 db 被破坏,它也不包含实际的 token (哈希不能被逆转...)
- 即使攻击者拥有 token ,他也无法通过更新字段来增加到期时间,因为到期日期在 token 本身中
现在首先,我想知道这是否是个好方法。
除此之外,我仍然没有弄清楚,在服务器上存储 AES 和 SHA256 key 的位置(我应该对它们进行硬编码吗?如果我将它们放入 web.config 或使用机器 key ,那么在负载情况下我会遇到问题平衡的服务器,...)。
最后,我在哪里存储 AES IV 向量,因为 Crypto.CreateEncryptor 需要它来解密?这是否意味着用户必须在每个请求中发送 token + IV?
我希望这是有道理的,我提前感谢您的回答。
更新:
好的,现在我做了更多的研究并得出了这个解决方案:
- token 将包含最初指定的数据(用户名、发行日期和超时)
- token 是用encrypt-then-mac生成的(它包括AES加密数据,IV向量+这2个值的标签用于认证,用HMACSHA265生成)
- token标签将被写入db
- 如果出现以下情况,用户将通过身份验证:
- 标签有效( token 认证)
- 数据可以解密
- token 还没有过期
- 标签与数据库中写入的标签匹配
- 用户未在数据库中被阻止(按需使 token 失效)
- key 将存储在 web.config 单独的部分中。每个服务器上都必须有相同的 key (当然是每个应用程序)
我没有使用 FormsAuthenticationTicket,因为在 .NET 中存在以下问题:
- 相同的 key 用于不同的目的(机器 key 用于 View 状态、资源和 formauthtickets)
- .NET 使用的 mac-then-encrypt 不被考虑 as safe as encrypt-then-mac
- 没有通往invalidate token before it is expired的内置方式
最佳答案
这是问题下评论线程的跟进。
您似乎对 OAuth 到底是什么感到有点困惑,所以希望我能在这里澄清一下。
OAuth 不是网络服务或您使用的东西。它是一种协议(protocol),描述了站点可以根据服务对用户进行身份验证的方式,而不允许站点知道用户的凭据是什么。作为一个附带的好处,大多数 OAuth 提供者还有一个 Web 服务来查询用户的信息,并且可以同时授予这样做的权限。
通常,您有兴趣从网站(例如 AcmeWidgets.com)的角度实现 OAuth,以便用户可以通过 Facebook 或 Google 或其他网站登录。但是,您也可以实现服务端(例如,Facebook 通常所在的位置),并允许其他人针对您进行身份验证。
例如,假设您有一个网络服务允许第三方站点为用户提供 Acme 品牌的 Widget。您的第一个第三方实现者是流行的 MyBook.org。流程看起来像这样:
- 有人邀请用户在他们的 MyBook 个人资料上使用“Acme Widgets”应用程序。
用户单击按钮,该按钮重定向到 AcmeWidgets.com。 URL 类似于:
http://acmewidgets.com/oauth/user?r=http%3A%2F%2Fmybook.org%2Foauth%2Fclient&appid=12345
- 询问用户是否允许 MyBook 访问他们的数据和提供小部件。
- 用户单击"is",Acme Widgets 随即注意到用户已允许它。
用户被重定向回 MyBook,URL 如下:
http://mybook.org/oauth/client?token=ABCDEFG
服务器端的 MyBook 现在获取该 token ,并将 Web 服务调用返回到 AcmeWidgets:
http://acmewidgets.com/oauth/validate?token=ABCDEFG&appid=12345&appsecret=67890
- AcmeWidgets 使用识别用户的最终身份验证 token 进行回复。
- 或者,它失败了,这意味着用户试图伪造 token ,或者他们拒绝了许可或其他一些失败情况。
带有 token 的 MyBook 现在可以调用 AcmeWidgets API:
http://acmewidgets.com/api/provision?appid=12345&token=ABC123&type=etc
这就是众所周知的 OAuth 舞蹈。请注意,这里有许多实现定义的内容,例如 URL、对各种 token 进行编码的方式、 token 是否可以过期或被撤销等。
希望这为您清除了一切!
关于c# - REST API token 认证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15321911/