我正在为将要生产和使用的REST服务设计API。我花了几天的时间试图弄清楚如何很好地处理身份验证,并认为我终于想出了一些办法。
我基于有关应用程序堆栈的以下事实提出此建议:
- 客户端和服务器位于.NET4中(客户端配置文件中的客户端部分)
- 服务器使用WCF REST公开
- 我真的不想在应用程序的内存中保留用户名和密码
从3开始,我想使用一种令牌身份验证的方式,以便在服务器验证了凭据之后,客户端将获得令牌以供整个应用程序的其余部分使用(这将使我能够做其他事情,例如使用户超时,并能够在网络版本和桌面版本之间无缝移动用户等)。在弄清楚如何使呼叫重播和防篡改之后,我提出了以下建议:
- 在客户端尝试进行身份验证之前,它会使用
ECDiffieHellmanCng
该类生成Diffie-Hellman密钥对。 - 它通过电线发送密钥对的公共部分以及用户名和密码(当然是通过HTTPS)。
- 服务器验证用户名/密码组合,如果成功,则执行以下操作:
- 创建一个唯一的会话令牌
- 生成自己的DH密钥对,并根据客户端提供的公共密钥计算共享密钥
- 记录其数据库中的会话令牌,共享机密,用户和“最后操作”时间(用于滚动到期窗口)
- 返回会话令牌,其公共DH密钥和身份验证成功消息
- 客户端从响应中获取DH密钥,计算共享密钥,并将令牌和密钥存储在内存中。
从那时起,会话令牌/秘密组合的工作方式与大多数其他REST API一样,对请求进行了指纹识别和时间戳记,然后生成了某种HMAC。每当客户端对服务器执行操作时,客户端都会检查令牌/秘密对,并允许该操作有效且未过期,并更新会话中的最后一个操作记录。
我看不到任何明显的缺陷,并且为此可能过度设计了,但是我需要在某个时候学习如何做到这一点。HMAC可以防止重放攻击,DH协商可以防止MITM攻击(我想不到在HMAC / DH之间可以进行有效的攻击)。
任何人都可以在此戳戳?