2013-10-16 228 views
10

我已经开始设计一个RESTful API,并且正在考虑如何处理身份验证。我想使用某种身份验证令牌,但无法使用类似的基础架构的OAuth,因此我必须自己处理它。在RESTful API中存储身份验证令牌的位置

一个对这个API的要求是它必须具有良好的性能,足以处理请求的高容量才会有规模的需要;我关心的是如何在每个请求上尽可能少地验证令牌(完整性,到期时间,IP地址等)所需的时间。

我想令牌应该某种哈希值,而不是包含用户信息的加密字符串,因为解密时间将是沉重的。

我读过我可以将令牌存储在内存散列表中,其中的关键是令牌,值是处理请求所需的用户信息,但是如何在集群环境中完成此项工作哪里会有每个“节点”的哈希表?

我应该把令牌上的数据库表的命中DB每次也可手动处理过期的门票保留?

也许它不是一个问题是重要的,但我使用Spring MVC中的问题的REST API。

在此先感谢。

+0

[REST API认证令牌]的可能重复(http://stackoverflow.com/questions/7919533/rest-api-authentication-tokens) – mayabelle

+0

@mayabelle感谢您的反馈。我不认为这篇文章涵盖了我的需求。我的问题是:如果我使用散列表或类似(我可能会使用Google Guava定时缓存),我如何在NLB环境中共享缓存?每次我必须检查代币还是有更好的方法时,我是否应该使用数据库来存储代币并在数据库中进行搜索? – Nicola

回答

3

我假设你使用https,因此所有的流量都被加密。我会建议以下原则之一。

基本身份验证

您可以请求的Authorization头添加凭据。这个证书是用Base64编码的(见下文)。这个证书可以在每个请求上发送,然后用你的数据库进行检查。为了让这个更快,更少的IO密集,你仍然可以使用缓存。一旦我实现了这样一个没有缓存的API,并且每秒能够处理数千个请求。

Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ== 

授权令牌

有实现与令牌你的想法不同的方式。一个常见的问题是每个API用户都有自己的令牌,通常称为API密钥,它永不过期。另一个是你首先必须授权(基本认证),然后得到一个过期的令牌。然后这一个被用作api密钥一段时间。

无论哪种方式,你必须决定是否使用高速缓存与否。我会保持简单,并进行基本身份验证,并每次检查数据库。几乎每个框架都对这种方法有很好的支持,因为它很简单。如果这会导致性能问题(我会推荐性能测试),尝试将您的凭证添加到JPA缓存中。如果你想实现一些使用过期令牌,可以看看Infinispan。

5

我同时使用一个内存中缓存和数据库高速缓存解决我的问题。以下是我的解决方案的总结,可以帮助任何人完成相同的任务。

  • 用户登录,并在那一刻生成一个唯一的密钥并发回给用户。
  • 登录令牌(基本上是一个带有某些处理的GUID)也存储在数据库表中,其中包含exipiration等附加信息以及用户的信息和角色。相同的信息段也存储在存储器中(谷歌番石榴哈希表,其中该令牌是关键)
  • 令牌必须与授权令牌每个API调用作为沿建议@ipa
  • 服务器代码检查是否被传递令牌在其内存缓存中,否则用户信息已经可用(例如,api调用在群集中的另一个节点上完成)令牌在令牌db中搜索一旦找到令牌,您可以检查到期,角色等等...

这给予了良好的性能和安全级别,令牌可以用任意任意字母即使是相对较慢的,因为您不必在每次api调用时重新计算它。这也适用于可以水平放大的无状态服务。

+1

你如何在客户端存储令牌?在内存中,cookie,本地存储?另外,我如何防范XSS和CSRF? – YarGnawh

+0

@YarGnawh现在我刚刚创建了服务器端Web服务RESTApi,我还没有一个Web应用程序。无论如何,我为wep应用做了一些测试,基本上我所做的是重写Spring安全筛选器以避免使用会话并将我的身份验证令牌存储在用户的Cookie存储中。我没有测试CSRF保护,但是通过这种方式使用spring安全性,即使使用像AngularJS这样的js前端框架,您也应该可以轻松利用其CSRF功能。 – Nicola

+0

为什么不直接将令牌存储在像redis这样的共享内存缓存中?这也很容易处理到期。 – splinter123

0

您可以在Redis中存储令牌。如果您要将其存储在数据库中,请确保优化服务器(如果您正在管理它)进行读取操作。我也有几个人在使用关键值存储的实现。哈希表也是个好主意。