6

我为 CakePHP 应用程序构建了一个简单的测试 API,它允许用户从移动设备(或任何设备)登录并获得 JSON 响应。此 API 可用于在 PhoneGap 中构建的移动应用程序。

登录方法如下所示:

public function login()
{
    if($this->request->is('post'))
    {
        // Use custom method in Model to find record with password params
        $findUser = $this->User->findUser(
            $_POST['username_or_email'],
            AuthComponent::password($_POST['password'])
        );

        // If a user exists and matches params
        if($findUser)
        {                           
            $this->User->id = $findUser['User']['id'];

            $this->autoRender = false;
            $this->response->type('json');
            $this->response->body(json_encode(array('authenticated'=>true,'message'=>__('You have been logged in successfully'))));
        }
        else
        {
            $this->autoRender = false;
            $this->response->type('json');
            $this->response->body(json_encode(array('authenticated'=>false,'message'=>__('Username or password is incorrect'))));
        }

    }
    else
    {
        $this->autoRender = false;
        $this->response->type('json');
        $this->response->body(json_encode(array('message'=>'GET request not allowed!')));
    }
}

移动设备(或任何 API 用户)可以发送他们的登录详细信息,然后他们将请求以 JSON 格式作为 true 或 false 进行身份验证。此布尔值不用于授予用户访问权限,而是告诉移动应用程序他们是否可以看到某些屏幕,并且他们只能获取数据或如果会话存在则可以发送数据!

如前所述,他们实际上也登录到设备上的 API 本身,因此如果他们直接(从该设备)访问网站,他们将有一个会话并看到相同的 JSON 响应。

因此,从本质上讲,用户在与服务器通信的设备上的会话期间保持登录状态。这与需要为每个请求传递的令牌不同,在此示例中它们有一个会话。

现在问题...

  1. 用户使用如上所示的会话“实际”登录到 API 是不好的做法吗?这似乎是处理设备身份验证的最安全方法,因为它使用与直接 Web 根目录相同的逻辑。

  2. 我已经看到一些 API 使用访问令牌,而不是我也实现了(用户返回他们的令牌而不是布尔值,并且没有创建会话)。但据我所知,这似乎需要更多工作,因为每次发出请求时,我都需要根据用户记录检查访问令牌。

4

4 回答 4

25

编辑
为了清楚起见,我不是 REST 的支持者,我是 RESTful/REST 类服务的支持者。如果您查看互联网上的所有 API,实际上很少有人坚持一个标准。您选择哪种方案将取决于您的特定问题空间。只需尝试确保安全并使用直观的设计选择(即,如果服务返回有关“狗”的信息,则不要将其命名为“猫”)
结束编辑

在 RESTful API 中管理某种形式的会话/令牌化方案是一种很好的做法。真正理想的(至少在我看来,关于这个问题有很多思想流派)设置涉及滚动令牌。

如果您完全关心 API 的安全性,那么权限应该在您的数据库层之外进行管理。是的,这会造成瓶颈,但这实际上是一件好事。每次都需要访问数据库来验证客户端的令牌会在整个过程中增加一个额外的步骤。这会减慢 API 的速度,而这实际上是安全系统所需要的。您不希望恶意个人能够每秒访问您的 API 3000 次,您希望他们的请求在(有点)相当大的几分之一秒内挂起。

这类似于MD5散列算法。他们中的许多人重新计算了几百次哈希,中间有随机的停顿。这有助于防止恶意客户端尝试暴力破解密码(通过使测试密码字符串的每个变体花费更多时间)。这同样适用于您的 API。

另一个好处是,如果您确实恶意用户试图一遍又一遍地登录,如果您是从数据库层管理他们,那么您可以标记他们的 IP 地址/用户名/what-have-you 并且只是在第 1 步放弃他们的请求。

无论如何,对于建议的过程(使用滚动令牌,如果看起来有点过分,您可以删除其中的一部分,但这是非常安全的):

  1. 用户点击“登录”服务,这需要用户名/密码,并返回两个令牌,一个私有访问令牌和一个公共请求令牌(服务器将这些令牌存储在数据库中)。
  2. 客户端将这些令牌存储在安全的地方
  3. 用户访问另一个端点以推/拉一些数据
    • 请求包含时间戳
    • 请求包括公共请求令牌
    • 请求包含访问令牌=> 此令牌应该是字符串的 MD5 散列,由将时间戳字符串连接到私有访问令牌字符串的末尾产生
  4. 服务器获取公共请求令牌,使用它来查找存储的私有访问令牌
    • 服务器获取该私有访问令牌,并连接时间戳字符串,然后获取该字符串的 MD5
    • 如果新的访问令牌与客户端发送给服务器的访问令牌匹配,HURRAY,此客户端已验证,因此推送/拉取数据
  5. (可选)服务器在每个请求上生成新的令牌,并将它们返回给客户端。这样每笔交易都会使旧令牌失效,并且如果发生某种中间人攻击,如果 VALID 用户已经完成了他们的请求,恶意用户现在拥有无效令牌并且无法开始搞乱你的 API。该方案试图确保恶意用户不会期望拦截服务器和客户端之间的单个通信,并且仍然可以访问系统。如果他们这样做了,那么真正的用户应该立即获得无效的令牌。然后应该触发他们的 API 客户端再次点击“登录”服务,获取新的有效令牌。这再次将恶意用户踢出系统。

这个方案不是 100% 安全的,任何用户访问系统都不会。通过在令牌上添加到期日期可以使其更加安全。此方案还具有额外的好处,您可以为用户/令牌分配特定权限(即只读访问,只能看到某些端点等)

这不是您做事的唯一方法,我会查找其他身份验证方案并从它们中获取您想要的内容(OAUTH是一个很好的起点,然后我会查看 Facebook/Twitter/Instagram)

于 2013-02-26T15:38:39.850 回答
3

让您的应用程序每次都登录,但不要像 Swayok 最后建议的那样使用登录密码对。当您登录时,服务器会生成一个令牌并将其返回给客户端。然后,客户端在发出请求时使用此令牌。对于每个请求,服务器都会检查令牌是否有效,如果有效,则执行请求。

这与会话的工作方式非常相似,服务器端框架在内部对其进行管理,并且这些令牌会不时过期。但是,正如 Swayok 正确指出的那样,您不需要会话,主要是因为您的 RESTful API 应该没有状态。您可以获得相同的实用程序,而无需存储有关用户的任何用户特定数据,并在每个请求中登录用户。

这是一篇很好的文章,或者您可以尝试使用 Facebook Graph API explorer 来查看它的实际效果

于 2013-02-26T00:23:47.880 回答
2

Restful API 完全限制使用会话和保存系统状态。每个请求都必须登录用户。访问令牌很棒,但也需要额外的处理。
最简单的方法是通过 HTTP Basic Auth(“授权”HTTP 标头)发送授权数据
http://www.httpwatch.com/httpgallery/authentication/
移动应用程序可以轻松做到这一点,并且很容易为每个请求添加此标头到 API。
在服务器端:

$username = env('PHP_AUTH_USER');  
$password = env('PHP_AUTH_PW'); 

并在 ApiAppController->beforeFilter() 中使用此数据处理用户登录

于 2013-02-20T17:20:43.880 回答
0

回答您的问题

  1. 只要您在应用程序关闭时关闭他们的会话并在需要时重新创建它,这不是一个坏习惯。这就像他们在他们知道的浏览器上登录并且可以注销一样,但是应用程序上也应该有相同的功能,否则他们可能已经关闭了应用程序,但实际上并没有结束他们的会话。您可以通过要求他们在关闭应用程序时注销自动检查来以多种方式处理此问题
  2. 令牌是执行上述操作的增强方式,但是您必须考虑令牌在传输时的安全性,并且服务器需要在每个请求上验证令牌。您已经说过这似乎需要更多的工作,所以是的,它需要更多的工作,如果您有时间或金钱限制并寻找答案来说明会话样式是否会在将来损害您的应用程序,只要您控制会话就不会并且在不结束会话的情况下不离开用户。如果你有时间,那么实施令牌,你会喜欢的。
于 2013-02-26T20:45:52.840 回答