REST API令牌认证

10

我刚开始开发我的第一个.NET REST API。由于它将是无状态的,所以我将使用令牌进行身份验证:

基本思路(System.Security.Cryptography):

  • AES用于加密+HMACSHA256用于完整性
  • 令牌数据将包含属性对象:用户名、发行日期和超时
  • 数据库将保存用户名、哈希密码和HMAC哈希

登录:

  • 检查凭据是否有效(用户名,将哈希密码与数据库值进行比较)
  • 如果为真,则加密数据对象
  • 在生成的令牌上使用HMAC并将其存储到数据库中
  • 将令牌(不包括HMAC)返回给用户(cookie/string)

需要身份验证的方法请求:

  • 用户每次发送令牌
  • 解密令牌
  • 如果过期,则出错
  • 如果未过期,请使用HMAC并将用户名+生成的哈希与数据库值进行比较
  • 如果数据库检查有效,则用户已通过身份验证

我认为,这种方法具有以下优点:

  • 即使数据库被攻破,它也不包含实际的令牌(哈希无法被反转...)
  • 即使攻击者拥有令牌,他也不能通过更新字段来增加过期时间,因为过期日期在令牌本身中

首先,我想知道这是否是一个好方法。

除此之外,我还没有弄清楚在服务器上存储AES和SHA256密钥的位置(我应该只是硬编码它们吗?如果我将它们放入web.config或使用机器密钥,则在负载平衡服务器的情况下会出现问题...)。

最后,我在哪里存储AES IV向量,因为Crypto.CreateEncryptor需要它进行解密?这是否意味着用户必须每次请求时发送令牌+IV?

我希望这有任何意义,并提前感谢您的回答。

更新:

好的,现在我做了更多的研究,并得出了这个解决方案:

  • token将包含最初指定的数据(用户名、发行日期和超时时间)
  • token使用encrypt-then-mac生成(它包括AES加密的数据、IV向量+用于验证这两个值的标记,使用HMACSHA265生成)
  • token标记将被写入数据库
  • 如果以下条件成立,用户将获得认证:
    • 标记有效(令牌认证)
    • 数据可以解密
    • 令牌尚未过期
    • 标记与写入数据库中的标记匹配
    • 用户没有在数据库中被阻止(按需使令牌无效)
  • 密钥将存储在web.config的单独部分。同样的密钥必须存在于每台服务器上(当然是对于每个应用程序)

我没有使用FormsAuthenticationTicket是因为在.NET中存在以下问题:


我很好奇,为什么要将数据存储在令牌内?如果您必须对其进行数据库验证,那么为什么不将数据存储在数据库中并仅使用Guid或其他随机令牌呢? - Joel Lucsy
1
由于令牌过期日期的原因 - 我想确保它不能在数据库中更新 + 如果已过期,则无需进行数据库查询。 - Pavle Gartner
1
你应该查看OAuth(http://oauth.net/),因为那基本上就是你在这里描述的。 - Mike Caron
1
@PavleGartner 从服务的角度来看:您可以选择您的权限,客户端将必须使用这些凭据。如果您希望该权限是您自己的数据库,那很好。只需自己进行验证即可! - Mike Caron
OAuth不是一个服务,而是一个协议。这个评论框无法充分解释细微差别,因此我会发表一个答案。 - Mike Caron
显示剩余2条评论
1个回答

7
这是在问题下的评论线程中的跟进。
您似乎对OAuth是什么有点困惑,所以希望我可以在这里澄清一下。
OAuth不是一个Web服务或者你可以消耗的东西。它是一种协议,描述了一个网站如何验证用户与服务的身份,而不允许该网站知道用户的凭据。作为一个副产品,大多数OAuth提供者还有一个Web服务来查询用户的信息,并且可以同时授予权限。
通常,您希望从站点(例如AcmeWidgets.com)的角度实现OAuth,以便用户可以通过Facebook或Google等登录。但是,您也可以实现服务端(例如通常会使用Facebook的地方),并允许其他人对您进行身份验证。
因此,例如,假设您有一个Web服务,允许第三方站点为用户提供Acme品牌小部件。您的第一个第三方实现者是流行的MyBook.org。流程看起来像这样:
1. 某人邀请用户在其MyBook个人资料上使用“Acme Widgets”应用程序。 2. 用户点击按钮,重定向到AcmeWidgets.com。 URL看起来像: http://acmewidgets.com/oauth/user?r=http%3A%2F%2Fmybook.org%2Foauth%2Fclient&appid=12345 3. 用户被问及是否允许MyBook访问其数据和提供小部件。 4. 用户点击“是”,随后Acme Widgets会注意到用户已允许它。 5. 用户被重定向回MyBook,URL如下: http://mybook.org/oauth/client?token=ABCDEFG 6. MyBook在服务器端现在获取该令牌,并将Web服务调用返回到AcmeWidgets: http://acmewidgets.com/oauth/validate?token=ABCDEFG&appid=12345&appsecret=67890 7. AcmeWidgets回复最终的身份验证令牌。 8. 或者,它失败了,这意味着用户试图伪造一个令牌,或者他们拒绝了权限或其他故障情况。 9. MyBook使用令牌现在可以调用AcmeWidgets APIs: http://acmewidgets.com/api/provision?appid=12345&token=ABC123&type=etc
所有这些都称为OAuth舞蹈。请注意,这里有许多实现定义的内容,例如URL、编码各种令牌的方式、令牌是否会过期或被撤销等。
希望这清楚地解释了一切!

谢谢,讲解得非常清楚。 - Pavle Gartner
我在网上找到的第一个地方,清晰简洁地描述了OAuth协议! - Chris W

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接