我的客户端都是浏览器。 所有客户端仅呈现一个从 Web API 获取数据的页面应用程序。 API 的设计遵循 REST 原则。
这是我的身份验证流程:
我的登录 View 使用基于 SSL 的基本身份验证。
如果用户发送的用户名和密码有效,我将 token 字符串放入响应中
此 token 存储在客户端的本地存储中
对服务器 API 的资源端点的每个进一步请求都包含 token 。
在我对 token 进行进一步调查(例如检查其到期日期)之前:
我需要知道 token 的真实性是否仍然有效或有人修改了它。这假设 token 之前是用 key 签名的。
或
我需要解密加密的 token 。
问题 1) 第 6 步和第 7 步使用 SSL 是否有意义?
问题 2) 让我们假设第 6 步和第 7 步有意义,那么我会执行以下操作:
当成功登录后创建例如 json 网络 token (JWT) 时,我使用 key 对其进行签名。此 key 位于服务器上的某处,可能存储在 xml 文件或单例类中。
无论我在创建 token 时将此签名 key 存储在何处,我都必须使用相同的 key 来验证 token 。这同样适用于 token 的加密。怎么可能在用户基础上对 token 使用不同的签名 key 。这意味着每个经过身份验证的登录都会获得一个带有单独签名 key 的 token 。
下次用户请求资源端点时,我想知道 token 是否仍然具有真实性。但我只能使用创建 token 时使用的相同签名 key 来检查这一点。
问题 3)这个签名 key 应该存储在哪里?
最佳答案
如果你使用 JWT,你有不同的安全可能性:
- 签署 token (参见
JWS
)。在这种情况下,中间人仍然可以读取此 token 的内容但无法修改它,因为他没有对其进行签名的 key ,并且当服务器检查 token 的真实性时,它将检测到它具有被篡改 - 加密 token (参见
JWE
)。在这种情况下,中间人无法读取 token 的内容,也无法修改其内容。
在您的案例中使用 SSL 可确保 token 不会被中间人窃取。因此,除非您在此 token 中存储了一些 super secret 信息,否则对其进行签名就足够了。显然签名 key 应该只存储在服务器上,而不是与世界其他地方共享。
就您关于根据用户使用不同 key 签署 token 的问题而言,我认为这没有必要。
我个人会使用仅包含最少信息的 JWT token ,例如 exp
和 jti
声明并使用 key 对其进行签名。然后我将使用此 token 的值作为服务器上键/值存储中的键(可以是某些缓存实现,如 memcached 或 NoSQL DB)并将用户名和任何其他必要信息关联到此 token 。该值将在 token 有效期内缓存。当客户端将 JWT token 发送到服务器时,服务器将验证 token 的签名以确保其值未被篡改,然后在缓存中查找关联的用户信息。
关于c# - 基于 token 的身份验证的签名/加密如何用于无状态服务器(REST),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21652392/