我试图理解token-based authentication
这些日子,它声称是一种stateless authentication
方法.我遇到了这个概念stateless web application
.
以下是我读过的一些主题:
使用Spring MVC进行无状态Web应用程序开发 (尚无响应)
无状态Spring MVC
如何使java Web应用程序完全无状态
如何使我的Web应用程序无状态但仍然做一些有用的事情?
起初,我对这个想法感到非常兴奋.但越来越多的我觉得stateless
是pseudo-proposition
.
例如,假设我们使用客户端存储的令牌进行身份验证,我们如何对在线用户进行统计(假设没有日志)?我们应该将令牌存储在DB中吗?这不是说我们在服务器上存储状态信息吗?更重要的是,DB中的名称,年龄等普通用户信息也是某种状态信息吗?
我认为这里真正的问题不是让网络应用程序无状态,而是让网络应用程序正确处理状态信息,这样它就不会危及可伸缩性.
这取决于如何解释这个词stateless
:
Web应用程序没有状态.
或者Web应用程序不会存储状态本身.
我更喜欢2,因为总会有一些inevitable global state
(引自@ deceze对他的答案的评论).无论我们将状态信息存储为HTML 5 Web存储,HTTP标头,隐藏表单字段还是Cookie,状态仍然存在.只是它存储在服务器以外的其他地方.
我错过了什么好事吗?任何人都可以对此有所了解,这样我可以从这种心理斗争中解脱出来吗?
添加1
刚刚看了一下这本书的RESTful Web服务通过Leonard Richardson
.在第4章的本节末尾Statelessness
,它将状态分为Application State
和Resource State
.因此,我之前提到的普通用户信息和数据,如图像等,可以归类为Resource State
.什么stateless
指的是Application State
.因此它不会破坏无状态代码存储resource state
在服务器上.
但该书还提到了这样一种情况:an application key is used to restrict how many times a user can invoke a web service.
它承认这些信息无法存储在客户端.并且必须将其存储在服务器端会破坏无状态代码并引入会话亲和性问题.它声称无状态可以避免会话亲和力问题但不解释如何. 我真的没有看到无国籍人如何处理这种情况.有人可以在这里说清楚吗?
"状态"仅指客户端和服务器之间的状态.当然服务器将存储数据,从技术上讲,您可以将服务器上任何数据的任何修改视为"更改状态".因此,在这种意义上的"无国籍"应用程序绝对没有实际意义.
"无状态"指的是服务器在任何特定时间是否处于允许特定客户端向其发送特定请求的状态.
考虑:使用传统的基于cookie的登录会话,服务器仅处于接受客户端在有限时间窗口内的请求的状态 ; 只要当前会话有效.客户无法预测这是多久.在任何时候,来自客户端的请求可能会失败,因为服务器上的某些状态超时.在这种情况下,客户端需要通过再次登录来重置服务器的状态.
与基于令牌的身份验证相比.令牌必须无限期有效.它本质上是用户名和密码的替代品.为了便于讨论,只需假设客户端在每次请求时都会发送用户名和密码.这意味着每个请求都可以根据其自身的优点进行身份验证,而不需要服务器处于某种特定的时间"状态".
您使用令牌而不是用户名和密码的原因有两个:
您可以使用同一帐户授权多个客户端,但每个客户端都使用其单独管理的凭据
您不希望每次请求都来回发送"主密码"
当然,服务器需要跟踪创建的令牌,并针对每个请求对某些数据库进行身份验证.这是一个不相关的实现细节.这与使用会话cookie没有区别; 但是,由于令牌无限期有效,因此可以更轻松地缓存请求,而不需要复制临时会话存储.
最后一个需要先发制人反击的潜在论点:无限期会话和无限期令牌之间的区别是什么?会话结束时与令牌可能被撤销时的区别是什么?
当会话结束时,可以使用其他一些"主凭证"重新建立(重新登录).令牌可以/应该仅在主动撤销时结束,这类似于撤销完全为主证书访问服务的授权,而不是常规应用程序流的一部分.
更一般地说:将无状态HTTP协议与FTP等有状态协议进行对比.在FTP中,服务器和客户端需要保持共享状态同步.例如,FTP协议具有更改当前工作目录的CWD
命令.也就是说,在任何给定时间都有一个客户"在其中"目录的概念.后续命令的行为会有所不同,具体取决于所处的目录.这是有状态的.您无法在不了解该状态的情况下随意发送命令,否则您将无法预测结果将是什么.
无状态客户端/服务器通信首先简化了客户端,因为客户端可以始终假设能够请求服务器的任何内容,而无需知道服务器的状态("我的会话是否仍处于活动状态? "," 此操作将影响哪个目录?").它可以帮助扩展服务器实现,因为只需要在所有服务器之间复制静态信息,而不是不断变化的有效会话池及其相关数据.
在架构上,您的目标应该是拥有尽可能多的无状态组件.这将简化扩展.例如,如果您的Web服务器保留了本地会话存储,那么很难将Web服务器扩展到负载均衡器/ CDN后面的多个实例.一个改进是将会话存储集中到一个独立的数据库; 现在,您可以拥有多个无状态 Web服务器,这些服务器知道如何从某个位置获取数据(包括会话数据)并可以呈现模板,但在其他方面完全可以互换.
但是,会话存储必须与试图访问它的每个人保持完美同步,这使得难以扩展它.令牌通过减少数据更改次数(仅在添加或删除令牌时)来改善这一点,这意味着如果您希望在多个位置拥有多个令牌存储,则可以使用分布式数据库或其他更简单的复制机制,和/或制作该数据可缓存.