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