使用Sessions vs Tokens进行API身份验证

时间:2013-02-17 20:24:09

标签: 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
        $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 个答案:

答案 0 :(得分:24)

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

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

如果您完全关心API的安全性,那么应该从数据库层管理权限。是的,这会造成瓶颈,但这实际上是一件好事。需要每次点击数据库以验证客户端的令牌,这在整个过程中增加了一个额外的步骤。这会降低API,这在安全系统中实际上是可取的。您不希望恶意个人能够每秒点击您的API 3000次,您希望他们的请求挂起(有些)相当大的一秒。

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

另一个好处是,如果你 DO 有恶意用户试图一遍又一遍地登录,如果你是从数据库层管理它们,那么你可以用红色标记他们的IP地址/ username / what-have-you,只需在步骤1中删除他们的请求。

无论如何,对于建议的过程(使用滚动令牌,如果看起来有点过分,你可以删除部分内容,但这是hella安全的):

  1. 用户点击“登录”服务,这需要用户名/密码,并返回两个令牌,一个私人访问令牌和一个公共请求令牌(服务器将这些令牌存储在数据库中)。
  2. 客户端将这些令牌存储在安全的地方
  3. 用户访问另一个端点以推送/拉取一些数据
    • 请求包含时间戳
    • 请求包含公共请求令牌
    • 请求包括访问令牌=>此标记应该是通过将时间戳字符串连接到专用访问令牌字符串末尾而产生的字符串的MD5哈希
  4. 服务器获取公共请求令牌,使用它来查找存储的专用访问令牌
    • 服务器获取私有访问令牌,并在时间戳字符串上连接,然后获取此字符串的MD5
    • 如果新的访问令牌与客户端发送服务器的密码匹配,HURRAY,此客户端已经过验证,那么推/拉数据
  5. (可选)服务器在每个请求上生成新令牌,并将它们返回给客户端。这样每个事务都会使旧令牌失效,如果发生某种中间人攻击,如果VALID用户已经完成了他们的请求,则恶意用户现在拥有无效令牌并且无法开始搞乱你的API。该方案试图确保恶意用户不能期望拦截服务器和客户端之间的单个通信,并且仍然可以访问系统。如果他们这样做,那么REAL用户应立即获得无效的令牌。然后应该触发他们的API客户端再次点击“登录”服务,获取新的有效令牌。这再次将恶意用户踢出系统。
  6. 此方案不是100%安全,也不会是用户访问系统。通过在令牌上添加到期日期,可以使其更安全。此方案还具有额外的好处,您可以为用户/令牌分配特定权限(即只读访问,只能看到某些端点等)

    这不是你可以做的唯一方法,我会查找其他身份验证方案,并从他们每个人那里得到你想要的东西(OAUTH是一个好的开始,然后我会看看Facebook /微博/ Instagram的)

答案 1 :(得分:3)

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

这非常类似于会话的工作方式,服务器端框架在内部管理它,这些令牌会不时到期。但是,正如Swayok右手指出的那样,你不想主要因为你是RESTful API应该没有状态会话。您可以获得相同的实用程序,而无需存储任何有关用户的用户特定数据,并在每次请求时记录用户。

这是一个good article,或者您可以尝试使用Facebook Graph API资源管理器来查看它的实际效果

答案 2 :(得分: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()

处理用户登录此数据

答案 3 :(得分:0)

回答你的问题

  1. 只要您在应用关闭时关闭会话并在需要时重新创建它,这不是一个糟糕的做法。它就像他们在浏览器上登录一样他们知道并且有登出的设施,但应该在应用程序上也可以使用它们,否则他们可能关闭了应用程序但实际上没有结束他们的会话。您可以通过要求他们在关闭应用程序时注销自动检查来以多种方式处理此问题
  2. 令牌是一种增强的上述方法,但您必须考虑令牌在传输时的安全性,并且服务器需要在每个请求上验证令牌。你说过它似乎更多的工作所以是的,它更多的工作,如果你有时间或金钱约束,并寻找答案,如果会议风格将来会损害你的应用程序,只要你控制会话并且不离开用户而不结束会话。如果你有时间然后实施令牌,你会希望如此。