使用会话与令牌进行API身份验证

使用会话与令牌进行API身份验证,api,cakephp,Api,Cakephp,我已经为CakePHP应用程序构建了一个简单的测试API,该应用程序将允许用户从移动设备(或任何相关设备)登录并获得JSON响应。此API可用于内置PhoneGap的移动应用程序 登录方法如下所示: public function login() { if($this->request->is('post')) { // Use custom method in Model to find record with password params

我已经为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的相同响应。

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

现在的问题是

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

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


  • Restful API完全限制使用会话和保存系统状态。每个请求都必须登录用户。 访问托克很好,但也需要额外处理。
    最简单的方法是通过HTTP基本身份验证(“授权”HTTP头)发送授权数据

    移动应用程序可以很容易地做到这一点,并且可以很容易地将每个请求的标题添加到API中。
    在服务器端:

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

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

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

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

    这里有一个关于此的示例,或者您可以尝试使用Facebook Graph API explorer查看它的实际操作

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

    在RESTful API中,管理某种形式的会话/令牌化方案是一种很好的做法。实际上,理想的设置(至少在我看来,在这个问题上有许多学派)包括滚动代币

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

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

    另一个好处是,如果您确实有一个恶意用户试图一次又一次地登录,如果您是从数据库层管理他们,那么您可以标记他们的IP地址/用户名/您拥有的内容,并在步骤1中删除他们的请求

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

  • 用户点击“登录”服务,这需要用户名/密码,并返回两个令牌,一个私有访问令牌和一个公共请求令牌(服务器将这些令牌存储在数据库中)
  • 客户机将这些令牌存储在一个安全的地方
  • 用户访问另一个端点以推/拉一些数据
    • 请求包含一个时间戳
    • 请求包括公共请求令牌
    • 请求包括一个访问令牌=>此令牌应该是字符串的MD5哈希,该字符串是将时间戳字符串连接到私有访问令牌字符串的末尾而产生的
  • 服务器获取公共请求令牌,使用该令牌查找存储的私有访问令牌
    • 服务器获取该私有访问令牌,并连接时间戳字符串,然后获取该字符串的MD5
    • 如果新的访问令牌与客户端发送给服务器的令牌相匹配,那么将验证该客户端,因此推/拉数据
  • (可选)服务器在上生成新令牌