他们说,计算机科学中最困难的两个问题是缓存失效和命名。老实说,这并没有错。这些都非常困难。
让命名变得困难的是清晰而简洁。变量、术语、函数或类的含义应该是毫无疑问的。如果您认为某个术语可能意味着两件事之一,那么它的名称不正确。
API 密钥和令牌就是这种情况。前几天我在一次讨论中,这两个词被互换使用。大约两分钟后,我不得不停止谈话并说:“你知道这些是不同的,对吧?
显然他们不知道。事实证明,很多人无法告诉我 API 密钥和令牌之间的区别。因此,让我们直截了当地记录。
我们可以通过以下定义来区分 API 密钥和令牌:
两者之间的创建方法通常也不同。
如果不讨论权限范围,就不会讨论身份验证。通过权限范围,我指的是授权部分或使用提供的身份验证方法时可以执行的功能。
每种方法的安全性如何?如果密钥或令牌被恶意用户泄露或获取,潜在损害有多严重?
那么,你什么时候会使用一个而不是另一个呢?看起来他们在利弊之间取得了很好的平衡。
现在我们了解了两者之间的区别,让我们看两个使用 Momento JavaScript SDK 的实际示例。
我确实说过,API 密钥通常是通过用户界面颁发的。考虑到这一点,我没有代码示例可以共享。但是,以下是您作为用户通过 Momento 控制台获取 API 密钥的方法。
您将选择所需的权限,设置可选的到期日期,然后生成。然后,您可以立即在工作流中使用 API 密钥。
与此形成鲜明对比的是,成功登录时颁发的基于用户的一次性令牌。我们可以举一个基于角色的示例,该用户对 calendar-events 缓存具有只读访问权限,但发布和订阅对主题的访问权限以进行协作。
// called on successful login
exports.handler = async (event) => {
const user = await loadUserMetadata(event.userId);
let token;
switch(user.role){
case 'data-entry':
token = await getDataEntryToken(user.tenantId);
break;
case 'admin':
token = await getAdminToken(user.tenantId);
break;
default:
throw new Error('Role not supported');
}
return token;
};
const getDataEntryToken = async (tenantId) => {
const scope = {
permissions: [
{
role: 'readonly',
cache: 'calendar-events',
item: {
keyPrefix: tenantId
}
},
{
role: 'publishsubscribe',
cache: 'collaboration',
topic: `${tenantId}-events`
}
]
};
const response = await authClient.generateDisposableToken(scope, ExpiresIn.minutes(15));
return {
token: response.authToken,
expiresAt: response.expiresAt.epoch()
};
};
可以在此处看到,我们创建了一个有效期为 15 分钟的令牌,其范围限定为功能的_只读_权限,并且仅允许访问以用户所属的 tenantId 开头的缓存项。因此,我们根据用户的属性限制了功能和数据。
API 密钥和令牌各有利弊。一个并不比另一个好。与计算机科学中的所有事情一样,这取决于您的用例。在决定要实现哪种身份验证机制时,请考虑用户将如何与应用程序交互。
是网络上基于用户的会话吗?使用令牌。也许你期望仅以编程方式访问,而无需确定可用数据的范围。使用 API 密钥。请随时将我们的参考表保存在顶部,以便快速参考。
无论您采取哪种方式,请记住确保您的数据安全。没有人希望数据泄露导致他们倒闭。注意安全。