我正在为一家公司开发移动应用程序。公司的每个人都有一个@company.com 电子邮件地址。该应用程序本身是机密的,因此只会安装在员工的设备上。此应用程序与外部服务器通信以存储和检索数据。
理想情况下,我想要完成的是让人们只需提供他们的电子邮件地址即可登录应用程序,而无需密码。这是我目前的想法:
- 新用户首次在特定设备上打开应用程序并输入他们的电子邮件地址。电子邮件地址与嵌入在应用程序中的静态令牌一起发送到服务器(对于应用程序的所有实例都是相同的)。
- 服务器验证令牌以及电子邮件地址是@company.com 的事实。它以仅用于该用户和设备的新令牌/密钥进行响应,客户端以纯文本形式存储在本地。该密钥实际上是用户的密码。它经过哈希处理,存储在服务器数据库中,并标记为禁用。
- 此时有两种可能:
- 服务器向该地址发送一封电子邮件,确认他们要在新设备上登录。该电子邮件包含一个链接,单击该链接会将密钥标记为已启用。需要对新设备请求进行速率限制,这样如果有人发现应用程序中嵌入的令牌,人们就不会收到垃圾邮件。
- 管理员专门批准新设备请求。
- 每个后续客户端对服务器的请求都必须包含密钥。
假设所有通信都通过 SSL,这听起来像是一种安全策略吗?有没有更安全或更简单的方法?
此外,生成将存储在客户端的令牌的最佳方法是什么?由于我希望用户只在他们第一次使用该应用程序时输入他们的电子邮件地址,我相信这个令牌永远不会改变。这是我当前基于 Drupal 的 drupal_get_token() 的算法(PHP):
// Usage: get_token($email) or get_token($client_token)
function get_token($value = '') {
$salt = hash('sha256', 'Some static, predefined phrase');
$hmac = base64_encode(hash_hmac('sha256', $email, $salt, TRUE));
return $hmac;
}
如您所见,它不能防止并行攻击(例如,如果有人找出了预定义的短语和算法并且他们可以访问数据库,他们可以生成哈希并将它们与存储在数据库中的哈希进行比较)但是因为原始键值已经很长我认为这不会像普通密码那样有效。此外,我不确定一种方法来创建一个动态盐,如果攻击者可以访问数据库(或者老实说,如果在这一点上它甚至很重要,因为访问数据库会暴露数据)无论如何,我们都在努力保密)。