我正在构建一个包含多个服务器的RESTful API,我想知道可以将访问令牌存储在中央数据库服务器中,然后,对于每个请求,通过查询数据库来验证此访问令牌是否有效并执行给定的动作。
如果我使用会话来完成这项工作,那么它会变成非RESTful吗?就像我将会话数据存储在数据库中一样?这对我来说一直是一个令人困惑的想法。
答案 0 :(得分:8)
REST代表 Representational State Transfer ,这个架构由Roy Thomas Fielding在chapter 5 of his dissertation中定义。
Fielding为REST架构定义了一组约束。其中一个约束是客户端和服务器之间的stateless通信,定义如下(他的论文中没有重点):
[...]从客户端到服务器的每个请求必须包含理解请求所需的所有信息,并且不能利用服务器上任何存储的上下文。 会话状态因此完全保留在客户端上。 [...]
因此,如果您在服务器上保留会话状态,则会中断stateless constraint。因此,它不是REST。在REST中,您在服务器上没有会话,因此您不会拥有会话标识符。
从客户端到服务器的每个请求都必须包含服务器要理解的所有必要信息。有了它,您不依赖于存储在服务器上的任何会话上下文。
例如,在访问需要身份验证的受保护资源时,每个请求必须包含所有必要的数据才能进行正确的身份验证/授权。这意味着将对每个请求执行身份验证。
请查看RFC 7235关于新身份验证方案注意事项的引用:
5.1.2. Considerations for New Authentication Schemes
HTTP身份验证框架的某些方面 对新身份验证方案的工作方式施加限制:
- HTTP认证被认为是无状态的:所有的 必须提供验证请求所需的信息 在请求中,而不是依赖于服务器记住 先前的请求。 [...]
身份验证数据(凭据)应属于标准HTTP Authorization
标头。来自RFC 7235:
Authorization
标头字段允许用户代理进行身份验证 本身与原始服务器 - 通常,但不一定,后 收到401
(未经授权)回复。它的价值包括 包含用户身份验证信息的凭据 代理请求的资源领域。Authorization = credentials
[...]
请注意,此HTTP标头的名称很不幸,因为它带有身份验证数据而不是授权。无论如何,这是发送凭据的标准标题。
执行基于令牌的身份验证时,令牌是您的凭据。在此方法中,您的硬凭证(用户名和密码)将交换为在每个请求中发送的令牌。同样,必须为每个请求执行身份验证,这样您就不会利用服务器上任何存储的上下文。
将您的令牌存储在服务器的某个位置非常有效。它不会打破REST架构的stateless constraint。
基本上,令牌可以是 opaque (除了值本身之外没有显示任何细节,比如随机字符串)或者可以自包含< / em>(例如 JSON Web Token ):
随机字符串:可以通过生成随机字符串并将其持久保存到具有过期日期且与其关联的用户标识符的数据库来发出令牌。
< / LI>JSON网络令牌(JWT):由RFC 7519定义,它是在双方之间安全地表示声明的标准方法。 JWT是一个独立的令牌,使您能够在有效负载中存储用户标识符,到期日期和任何您想要的内容(但不要存储密码),这是{{3编码为JSON。客户端可以读取有效负载,并且可以通过验证服务器上的签名来轻松检查令牌的完整性。如果您不需要跟踪JWT令牌,则不需要坚持使用JWT令牌。尽管如此,通过持久存在令牌,您将有可能使其无效并撤销其访问权限。要找到一些与JWT合作的优秀资源,请查看Base64。
有http://jwt.io您可以持久保存令牌。根据您的要求,您可以探索不同的解决方案,例如many databases,relational databases或key-value stores。
答案 1 :(得分:2)
您的RESTful API需要无状态。无状态意味着它应该不依赖于先前的通信,例如在相关请求之前设置的身份验证和cookie。
但这并不意味着您无法在服务器端缓存某些身份验证令牌,前提是客户端可以在没有它的情况下发出请求。这意味着,如果客户端可以在每个请求上回退到标准HTTP身份验证,那么它应该仍然可以。这样做的目的是在服务器端启用负载平衡,分发和无(或有限)内存用于对话。
除此之外,如果您不打算使用它提供的好处,那么您并不需要 来遵守所有“规则”。如果您愿意,只要知道了传统,您就可以以任何方式实施它。
编辑:找到之前关于该主题的讨论:Do sessions really violate RESTfulness?