13

对于REST风格的Web服务,我们说服务器不应该存储任何状态。现在,对于每个请求,“用户”必须经过认证,并且必须拥有他/她希望执行的操作的授权。RESTful认证 - 导致高负载性能不佳?

现在每个请求都会包含该用户的授权数据。这里是我的困惑:

假设主页上有一个登录名和密码字段。用户输入发回服务器的用户名/密码,用户验证,然后返回“某个标记”。现在,这个令牌会在每个请求中发送到服务器。问题(S):

  • 是否后端数据库需要有一个单独的表来存储这些 令牌通过用户名索引?
  • 假设令牌存储在数据库中,则每个请求都需要进行数据库调用。在高负载时这不会使数据库服务器成为瓶颈吗?
  • 如果令牌没有真正存储在数据库中什么是最好的“平静”存储的地方?
  • 进行会话可能不太安宁,但是我没有看到如何平衡认证/授权(w.r.t.上述几点)?
  • 如果它不是一个令牌,那么用户名/密码是否需要被反向发送? (听起来像个坏主意:)

我可能会误解RESTful认证/授权的概念。但是,对于每个http请求,“服务”需要访问数据库来验证凭据,情况真的如此吗?有什么能够缩短流程的时间,并且仍然忠于宁静的原则吗?我可以想到有一个缓存存储细节,并在服务器重启的情况下,它只是让数据库的旅程。这只是一个性能优势,可能会使系统复杂化(也许值得,不知道)。这是唯一的解决方案吗?

因此,从REST的理论/概念角度(不是必需的实现),这个问题是如何处理的(如果完全是问题)?你的专业经验如何处理这个问题以及这种方法有多安静?我有一个Restlet + J2EE + MySQL Restful web服务,我有这个问题弹出,但没有满意的答案(Google,Stackoverflow等),我知道HTTP的基本和摘要授权,但我'根据上面的解释,不熟悉存储/检索的内部。

+1

一般准则:您使用磁盘/数据库的次数越少,应用程序可以实现的负载越高。 – bestsss 2011-03-05 12:17:09

回答

8

REST的精神是无国籍。这并不意味着客户端状态不能被服务持久化,但实际上这意味着客户端状态由服务器保存在内存通常是一件坏事。

而是保持在内存中的认证数据,或每次去到DB进行核查的,你所能做的就是保持功能存储器(即代码),用于与隐窝/解密的用户信息。这是也被建议的技术:

What should I store in cookies to implement "Remember me" during user login

因此,举例来说,你会做的是以下几点:

  1. 当客户第一次接触到的服务,它没有Cookie 。
  2. 您发出一个包含用户信息的Cookie,并使用您的功能对其进行“签名”(所有服务器运行您的代码都可以)
  3. 当客户端再次联系服务时,检查它是否有Cookie;如果不是,重复(2)。
  4. 但是,如果确实存在cookie,则尝试解密(再次使用在您的基础架构中复制的单一功能),并验证是否可以展开并摘录该用户ID信息。
  5. 这将验证用户并为您提供身份信息,所有操作都不会超过必要的数据库次数。它是RESTful。

请记住,我描述的这个“函数”并不是一件新奇的事情 - 它是一个标准的安全散列,但是基于一个唯一的私钥,只有你的集体服务器知道。并且可以根据需要旋转这样的键等。

+0

@kvista:好点。我正在考虑同样的“概念”,但不能那么清楚。因此,如果解决了认证问题,那么同样的技术是否可以“外推”出来,也可以用于授权?这就是在数据库中坚持的'业务规则'的概念 - 我不确定授权是否是一件好事。想法? – PhD 2011-03-04 22:29:06

+0

@Nupul:在你的“加密的cookie值”中,你可以存储你想要的任何东西 - 用户名,ID,认证信息(角色)等。所以是的,我认为这是可能的;取决于认证信息在何种程度上是数据驱动的(在这种情况下,在数据库中查找是有用的)。顺便说一句,请记住,整个饼干的事情,重要的是看看到期的问题;例如,删除其帐户的用户应删除其Cookie。 – kvista 2011-03-04 23:20:02

+0

@kvista:关于删除的好处。在我们系统的情况下,用户不能删除帐户,但系统管理员可以 - 通过访问数据库:)假设我在时间= t删除帐户,cookie在t + 5时过期,但用户其账户现在被删除的人试图在t + 2时使用'cookie'访问系统 - 那么是什么?我们是否应该依靠外键约束失败?有些人可能不会! – PhD 2011-03-05 00:52:36

3

您只在登录时验证凭证(例如用户名/密码)。当用户成功登录时,您向他们发送一个包含无法猜测的“会话ID”的cookie。此会话ID成为在证书被检查后允许进一步访问的令牌。服务器应用程序通过在某些内存数据结构中查找令牌来验证该令牌。令牌在一段合理的时间后过期,以防止内存耗尽。如果用户明确注销(按下“注销”按钮),则令牌将显式从内存存储中删除。

在发送和接收令牌时使用https很重要 - 否则嗅探令牌会让黑客“劫持会话”。换句话说,从登录到注销的整个应用程序工作流使用https。

+0

@健康:这种策略会在服务器重启后生存吗?内存中的数据结构是否也需要存储在持久性存储中(回到方块1)?那么这不就是我刚才提到的缓存吗? – PhD 2011-03-04 21:48:43

+0

所以这只是一个普通的用户会话,使用JSESSIONID cookie?也许OP认为这是一种状态,因此不属于RESTful架构? – 2011-03-04 21:49:53

+0

不,它不会在重新启动后继续存在,除非您在重新启动时坚持它。有一种方法可以解决这个问题,不需要经常重新启动服务器,并且要求用户重新登录,而不是在重新启动时继续会话。 – 2011-03-04 21:50:36

2

REST式服务应该是无状态的,所以是的,客户端每次调用RESTful服务时都需要提供身份验证凭证。

用某种散列或标记或会话ID替换用户名/密码并没有真正的好处。所有这些都只是不同形式的身份验证,必须针对持久存储中的一些数据进行验证。会话和令牌的缺点是它们违反了无状态要求。

如果数据库性能出现问题,请使用memcached或其他一些高性能数据缓存。您可能会发现,您的所有数据库访问都受益于此,而不仅仅是检索授权凭证。

最后,只要您通过HTTPS进行操作,每次发送用户名/密码都没有问题。永远不要通过纯文本HTTP发送重要的认证凭证。

+2

每次发送U/P肯定有缺点:客户端必须保留它,而不是在它传递到服务器时立即丢弃它,从而使客户端不太安全。在一些方案中,这可能不太安全。另一个缺点是速度:验证令牌或cookie可能比验证U/P更快,特别是如果您已使用密码哈希(如bcrypt)正确加密了密码。 – 2012-09-26 20:08:51