通过将用户的id +时间加密为JSON来创建访问令牌

时间:2015-04-30 21:20:44

标签: php api security encryption access-token

我正在制作API而我是新手。我想到了创建访问令牌的想法。基本上,我们使用密钥加密JSON数据,将其转换为Base64并将其作为访问令牌返回。之后,API解密访问令牌并可以使用id。 E.g:

login method: 我们检查用户名/密码是否正确,如果是,那么我们从数据库中获取用户的id。然后我们构造访问令牌,它将在未来的API调用中使用,如下所示:

  1. 我们制作一个JSON字符串,例如{"user_id":609, "logintime":"1430428180"}
  2. 我们使用加密功能(例如these)并使用我们的加密密钥加密该JSON字符串。
  3. 我们将加密的字符串转换为Base64,因此它是可读的并将其作为访问令牌返回。
  4. 稍后,当用户执行操作时,我们可以使用此访问令牌来了解用户。 E.g:

    update user info method:我们发送的数据需要更新,并且我们之前获得了访问令牌。然后我们:

    1. Base64解码访问令牌。
    2. 使用我们的加密密钥对其进行解密。
    3. 解析JSON数据,我们知道用户的ID,因此我们可以轻松更新数据库。此外,我们知道API调用是合法的,因为解密的字符串是JSON,它包含user_idlogintime字段。
    4. 这种做法有什么好处吗?

2 个答案:

答案 0 :(得分:10)

在这个答案中,我将更多地关注API安全性,我认为这是问题背后的真正问题(OP对我的第一个答案的评论提示)。

API密钥的用途

API密钥用于登录用户困难,不可能或不合需要的情况。 API密钥用于身份验证,"证明我是谁" API访问的一部分。 授权,或者"我被允许这样做"通常存储在服务器上。

有效API访问的标准

为了让您对请求有效感到满意,您必须考虑几点。

  1. 请求是否来自授权用户?
  2. 请求是否在传输过程中被篡改?
  3. 为了确保第1点在一段时间内保持为真,API也应该担心密钥保持机密。

    1. 此请求不会损害未来请求的有效性。
    2. 请注意,尽管API密钥通常作为HTTP标头发送,但为了简单起见,我将在我的示例中使用GET变量。

      单键API

      某些API设置为使用单个密钥进行访问。我们使用CEgJu8G483u3作为示例键。

      用户将通过

      之类的请求发送
      GET /users?apiKey=CEgJu8G483u3 HTTP/1.1
      Host: api.bigorg.com
      

      如果API通过HTTP进行通信,则固有不安全:

      1. 密钥可由任何爱管闲事的第三方公开阅读(因此可用)。
      2. 第三方可以随意篡改请求的正文,服务器也不知道。
      3. 因此,在通过HTTP进行单键API身份验证时,违反了安全标准1 - 3。

        如果您的单一密钥API通过HTTPS 进行通信,那么1 - 3仍然有效并且可以被认为是安全的。

        摘要或签名API

        Google和亚马逊使用此方法访问其许多API。

        当服务器授予对其系统的访问权限时,会生成两个键,标识符密码

        ACCESS_IDENTIFIER = 'bill';
        ACCESS_SECRET = 'U59g5LcBBZpw';
        

        一旦生成了两个密钥,客户端和服务器就会存储秘密的副本,而这个密钥永远不会再被直接传输。

        在此系统下发出请求时,标识符随请求一起提供(请注意,访问密钥可能与随机生成的字符串一样复杂,或者与尝试访问系统的用户的ID一样简单。

        在客户端发送请求之前,生成请求的摘要,然后使用先前商定的秘密加密。生成签名的方法各不相同,但现在常见的方法是HMAC

        请求看起来像这样

             GET /users?identifier=bill&signature=JjU1j1fIH62KG7FCTdZGzK7J HTTP/1.1
             Host: api.bigorg.com
        

        此示例中使用的随机伪签名

        如果在生成签名时包含请求正文,您现在可以安全地进行身份验证。

        请注意,收听HTTP流量仍然非常简单,因此未经授权的知识仍然存在问题,但是收听方无法发送自己的请求或篡改您的请求。

        如果请求被篡改,签名将失效,请求将被拒绝。

        JSON Web令牌(您的解决方案)

        您的解决方案几乎与JSON Web Tokens完全相同,因此我只是假装您正在使用它。

        此解决方案通过HTTPS安全。 ( DO 使用HTTPS)

        1. 请求来自有效的用户=> 他们知道令牌
        2. 请求未被篡改=> HTTPS可防止第三方篡改请求
        3. 访问密钥仍为秘密=> HTTPS阻止第三方阅读您的访问密钥
        4. 如果您的API使用HTTP /纯文本,您可以使用您的JSON Web代币作为访问密钥,但您还需要生成私有密钥并使用它来为请求添加签名。

          请注意,如果您正在使用HTTP,我不确定您将如何将密码传输到客户端。也许通过蜗牛邮件或电子邮件?

          结论

          你的想法被非常聪明的人所复制。恭喜!这意味着这是一个好主意!

          只要您使用HTTPS,您的访问密钥解决方案就是可靠的。

答案 1 :(得分:0)

在进行身份验证,访问令牌,您拥有什么时,您通常会更好地使用经过验证的图书馆,这个图书馆的人比我们两个人都聪明得多。

创建

Json Web Tokens或JWT是为了解决这类问题(以及其他问题)。它has a PHP library

因此,为用户创建访问令牌将如下所示。 (解释自述)

<?php

$key = "my-secret-key-here";
$token = array(
    "user_id": 1
);

$jwt = JWT::encode($token, $key);

/**
  * $jwt is your JSON web token, it will look something like this:
  *
  * eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiMSJ9.TcXz_IwlmxO5nPd3m0Yo67WyYptabkqZW4R9HNwPmKE
  *
  **/

$decoded = JWT::decode($jwt, $key, array('HS256'));

print_r($decoded);

/*
 NOTE: This will now be an object instead of an associative array. To get
 an associative array, you will need to cast it as such:
*/

$decoded_array = (array) $decoded;

?>

因此,在回答您的问题时,您已走上正轨! JWT似乎完全按照您在此处描述的内容进行操作,因此我选择了经过更全面测试的库的安全性。