通过将用户的 ID + 时间加密为 JSON 创建访问令牌
Creating access token by encrypting user's id + time as JSON
我正在制作一个 API 并且 我是新手 。我想到了创建访问令牌的想法。基本上,我们用密钥加密 JSON 数据,将其转换为 Base64 并将其 return 作为访问令牌。稍后,API 解密该访问令牌并可以使用该 ID。例如:
login method
:
我们检查 username/password 是否正确,如果正确,则我们从数据库中获取用户 ID。然后我们构建访问令牌,它将在以后的API调用中使用,像这样:
- 我们制作一个 JSON 字符串,例如
{"user_id":609, "logintime":"1430428180"}
- 我们使用加密函数(例如 these)并使用我们的加密密钥加密 JSON 字符串。
- 我们将加密字符串转换为 Base64,因此它是可读的并且return将其作为访问令牌。
稍后,当用户进行操作时,我们可以使用此访问令牌来了解用户。例如:
update user info method
:我们发送需要更新的数据和我们之前获得的访问令牌。那么我们:
- Base64 解码访问令牌。
- 使用我们的加密密钥对其进行解密。
- 解析JSON数据,我们知道用户的id,所以我们可以很容易地更新数据库。此外,我们知道 API 调用是合法的,因为解密的字符串是 JSON 并且它包含
user_id
和 logintime
字段。
这个方法好用吗?
当涉及身份验证、访问令牌等方面时,您通常最好使用一个比我们都聪明得多的人创建的经过验证的库。
Json Web Tokens or JWT, were created to solve exactly this sort of problem (among others). And it 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 似乎完全符合您在此处描述的内容,因此我会选择经过更彻底测试的库的安全性。
在这个答案中,我将更多地关注 API 安全性,我认为这是问题背后的真正问题(由 OP 对我的第一个答案的评论提示)。
API 键的用途
API 密钥用于用户登录困难、不可能或不希望登录的情况。 API 密钥用于 Authentication,API 访问的 "proof of who I am" 部分。 授权,或者"I am allowed to do this"通常存储在服务器上。
有效 API 访问条件
为了让您确信请求有效,您必须考虑两点。
- 请求是否来自授权用户?
- 请求是否在传输过程中被篡改?
为了确保第 1 点随着时间的推移成立,API 还应该担心密钥 保持 秘密。
- 此请求不会损害以后请求的有效性。
请注意,虽然 API 密钥通常作为 HTTP headers 发送,但为了简单起见,我将在示例中使用 GET 变量。
单键API
一些 API 设置为使用单个密钥进行访问。让我们使用 CEgJu8G483u3
作为示例键。
用户会发送类似
的请求
GET /users?apiKey=CEgJu8G483u3 HTTP/1.1
Host: api.bigorg.com
如果 API 通过 HTTP 通信,这 本质上 不安全:
- 任何爱管闲事的第 3 方都可以公开读取(因此可以使用)该密钥。
- 第3方可以随意篡改请求的body,而服务器是不知道的。
因此在通过 HTTP 的单密钥 API 身份验证中,违反了安全标准 1 - 3。
如果您的单个密钥 API 仅通过 HTTPS 进行通信,那么 1 - 3 仍然有效并且可以被认为是安全的。
摘要或签名APIs
这种方法被 Google 和亚马逊用于访问他们的许多 API。
当服务器授予对其系统的访问权限时,会生成 两个 密钥,一个 identifier 和一个 secret.
ACCESS_IDENTIFIER = 'bill';
ACCESS_SECRET = 'U59g5LcBBZpw';
一旦生成了两个密钥,客户端和服务器就会存储一份秘密副本,永远不会再直接传输。
当在该系统下发出请求时,标识符随请求一起提供(请注意,访问密钥可以像随机生成的字符串一样复杂,也可以像尝试访问的用户的id一样简单系统.
就在客户端发送请求之前,会生成请求的摘要,然后使用先前商定的秘密对其进行加密。生成签名的方法多种多样,但目前常见的是HMAC。
然后请求看起来像这样
GET /users?identifier=bill&signature=JjU1j1fIH62KG7FCTdZGzK7J HTTP/1.1
Host: api.bigorg.com
本例中使用的随机pseudo-signature
如果在生成签名时包含请求 body,您现在可以安全地进行身份验证。
请注意,监听HTTP流量仍然非常非常简单,因此未经授权的知识仍然是一个问题,但监听方无法发送自己的请求或篡改您的请求。
如果请求被篡改,签名将失效,请求将被拒绝。
JSON Web 令牌(您的解决方案)
您的解决方案与 JSON Web Tokens 几乎相同,所以我假设您正在使用它。
此解决方案通过 HTTPS 是安全的。 (DO 使用 HTTPS)
- 请求来自有效用户=> 他们知道令牌
- 请求未被篡改 => HTTPS 防止第 3 方篡改请求
- 访问密钥保密 => HTTPS 防止第 3 方读取您的访问密钥
如果您的 API 使用 HTTP/plaintext,您可以使用 JSON Web 令牌作为访问密钥,但您还需要生成一个私人秘密并使用它为请求添加签名。
请注意,如果您使用 HTTP,我不确定您将如何将机密传输到客户端。也许通过蜗牛邮件或电子邮件?
结论
你的想法已经被非常聪明的人复制了。恭喜!这意味着这是个好主意!
如果您使用 HTTPS,您的访问密钥解决方案是可靠的。
我正在制作一个 API 并且 我是新手 。我想到了创建访问令牌的想法。基本上,我们用密钥加密 JSON 数据,将其转换为 Base64 并将其 return 作为访问令牌。稍后,API 解密该访问令牌并可以使用该 ID。例如:
login method
:
我们检查 username/password 是否正确,如果正确,则我们从数据库中获取用户 ID。然后我们构建访问令牌,它将在以后的API调用中使用,像这样:
- 我们制作一个 JSON 字符串,例如
{"user_id":609, "logintime":"1430428180"}
- 我们使用加密函数(例如 these)并使用我们的加密密钥加密 JSON 字符串。
- 我们将加密字符串转换为 Base64,因此它是可读的并且return将其作为访问令牌。
稍后,当用户进行操作时,我们可以使用此访问令牌来了解用户。例如:
update user info method
:我们发送需要更新的数据和我们之前获得的访问令牌。那么我们:
- Base64 解码访问令牌。
- 使用我们的加密密钥对其进行解密。
- 解析JSON数据,我们知道用户的id,所以我们可以很容易地更新数据库。此外,我们知道 API 调用是合法的,因为解密的字符串是 JSON 并且它包含
user_id
和logintime
字段。
这个方法好用吗?
当涉及身份验证、访问令牌等方面时,您通常最好使用一个比我们都聪明得多的人创建的经过验证的库。
Json Web Tokens or JWT, were created to solve exactly this sort of problem (among others). And it 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 似乎完全符合您在此处描述的内容,因此我会选择经过更彻底测试的库的安全性。
在这个答案中,我将更多地关注 API 安全性,我认为这是问题背后的真正问题(由 OP 对我的第一个答案的评论提示)。
API 键的用途
API 密钥用于用户登录困难、不可能或不希望登录的情况。 API 密钥用于 Authentication,API 访问的 "proof of who I am" 部分。 授权,或者"I am allowed to do this"通常存储在服务器上。
有效 API 访问条件
为了让您确信请求有效,您必须考虑两点。
- 请求是否来自授权用户?
- 请求是否在传输过程中被篡改?
为了确保第 1 点随着时间的推移成立,API 还应该担心密钥 保持 秘密。
- 此请求不会损害以后请求的有效性。
请注意,虽然 API 密钥通常作为 HTTP headers 发送,但为了简单起见,我将在示例中使用 GET 变量。
单键API
一些 API 设置为使用单个密钥进行访问。让我们使用 CEgJu8G483u3
作为示例键。
用户会发送类似
的请求GET /users?apiKey=CEgJu8G483u3 HTTP/1.1
Host: api.bigorg.com
如果 API 通过 HTTP 通信,这 本质上 不安全:
- 任何爱管闲事的第 3 方都可以公开读取(因此可以使用)该密钥。
- 第3方可以随意篡改请求的body,而服务器是不知道的。
因此在通过 HTTP 的单密钥 API 身份验证中,违反了安全标准 1 - 3。
如果您的单个密钥 API 仅通过 HTTPS 进行通信,那么 1 - 3 仍然有效并且可以被认为是安全的。
摘要或签名APIs
这种方法被 Google 和亚马逊用于访问他们的许多 API。
当服务器授予对其系统的访问权限时,会生成 两个 密钥,一个 identifier 和一个 secret.
ACCESS_IDENTIFIER = 'bill';
ACCESS_SECRET = 'U59g5LcBBZpw';
一旦生成了两个密钥,客户端和服务器就会存储一份秘密副本,永远不会再直接传输。
当在该系统下发出请求时,标识符随请求一起提供(请注意,访问密钥可以像随机生成的字符串一样复杂,也可以像尝试访问的用户的id一样简单系统.
就在客户端发送请求之前,会生成请求的摘要,然后使用先前商定的秘密对其进行加密。生成签名的方法多种多样,但目前常见的是HMAC。
然后请求看起来像这样
GET /users?identifier=bill&signature=JjU1j1fIH62KG7FCTdZGzK7J HTTP/1.1
Host: api.bigorg.com
本例中使用的随机pseudo-signature
如果在生成签名时包含请求 body,您现在可以安全地进行身份验证。
请注意,监听HTTP流量仍然非常非常简单,因此未经授权的知识仍然是一个问题,但监听方无法发送自己的请求或篡改您的请求。
如果请求被篡改,签名将失效,请求将被拒绝。
JSON Web 令牌(您的解决方案)
您的解决方案与 JSON Web Tokens 几乎相同,所以我假设您正在使用它。
此解决方案通过 HTTPS 是安全的。 (DO 使用 HTTPS)
- 请求来自有效用户=> 他们知道令牌
- 请求未被篡改 => HTTPS 防止第 3 方篡改请求
- 访问密钥保密 => HTTPS 防止第 3 方读取您的访问密钥
如果您的 API 使用 HTTP/plaintext,您可以使用 JSON Web 令牌作为访问密钥,但您还需要生成一个私人秘密并使用它为请求添加签名。
请注意,如果您使用 HTTP,我不确定您将如何将机密传输到客户端。也许通过蜗牛邮件或电子邮件?
结论
你的想法已经被非常聪明的人复制了。恭喜!这意味着这是个好主意!
如果您使用 HTTPS,您的访问密钥解决方案是可靠的。