2015-02-23 30 views
10

我已经构建了一个API来为登录的用户生成身份验证令牌。此时我还有一个用Node.JS编写的客户端应用程序。
当我使用用户证书从客户端应用程序向API发出请求时,我获得身份验证令牌:我应该如何将其存储在客户端应用程序中?我不应该在每次想要提供API请求时都要求提供令牌,对吗?
我想过把令牌放在Cookie中,但我不认为这是最好的解决方案。 你会推荐什么?我应该如何存储由RESTful API生成的令牌?

+0

是您的客户端应用程序,它是一个node.js服务器,使用任何数据存储? – 2015-02-23 13:36:35

+0

我使用的是MongoDB – IgorSousaPT 2015-02-23 13:38:09

+0

,您可以像redis一样制作内存数据存储以存储令牌并将其用于进一步请求。使用会话存储和connect-redis是一个可行的解决方案。 – 2015-02-23 13:48:56

回答

5

成功登录后,一个唯一的一次性令牌应该创建在服务器端,并存储在数据库中,并与用户ID和时间戳相对应。您将令牌存储在Cookie客户端。然后您将令牌传递给每个后续的API调用。然后服务器应该检查令牌是否有效(即未过期,比如发出或更新少于30分钟前)。如果它是有效的,您可以检索针对该标记存储的用户详细信息,并执行您需要的任何后端功能(如用户的身份验证)。然后,您更新该令牌的时间戳(刷新会话,因为您希望登录在超过30分钟没有用户交互后超时)。如果您获取API调用时令牌已过期或不存在,请重定向至登录页面。

此外,您可能已经知道这一点,但要确保令牌是唯一且不可猜测的,我倾向于生成新的随机GUID并加密它们,请勿使用sequentail ID或类似的东西。

+0

是的,我知道这个独特和不可猜测的部分,不过谢谢你指出它。我关于cookies方法的问题是,它安全吗?难道不可能窃取cookie值并访问其他用户的私人信息吗? – IgorSousaPT 2015-02-23 14:06:17

+0

假设您使用的是SSL,那么使用中间人攻击难以理解价值。使用唯一的过期令牌会在使用后使令牌无效,所以相对安全。假设用户在会话期间保持相同的IP(可能),您也可以使用ip验证该令牌。 但是,有可能是客户端上的所有cookie信息上传至第三方网站的恶意代码,但如果正确实施,我认为使用cookie对于大多数Web应用程序来说已足够安全。或者,你可以看看OAuth,这是另一个头痛的问题,但是广泛使用的auth方法。 – 2015-02-23 14:25:19

+0

实际上,我使用OAuth2.0来验证凭据并生成令牌。但是我仍然需要将令牌存储在客户端。除非,我得到这个非常错误! – IgorSousaPT 2015-02-23 15:04:41

1

我认为这个链接可以帮助你:

事实上,你应该有一个截止日期的标记,所以在发送请求之前,您不必每次都获取新令牌。当令牌过期时,您只需从服务“刷新令牌”中获取新的令牌。

关于如何将令牌存储在客户端应用程序中的问题,我认为您可以将其保存在内存(地图或嵌入式数据库)中。

否则结束,我不认为在这种用例中使用cookie是一个好主意。

希望它能帮助你。 Thierry

1

我们正在研究一个使用非常类似方法的应用程序。客户端应用程序是一个静态HTML5/JS单页面应用程序(不需要任何服务器端生成)并与API服务器进行通信。

最好的方法是将会话令牌存储在内存中:也就是说,在JS代码中的一个变量内。如果您的客户端应用程序是单个页面,那不应该是个问题。
除此之外,我们还将会话令牌保留在sessionStorage中以便在用户刷新页面时保留它。为了在创建新选项卡时保留标记(sessionStorage特定于浏览器窗口),我们还在关闭页面时将其存储在localStorage中,并将其与打开标签的计数器一起存储(当应用程序的所有选项卡都关闭时,我们删除令牌。

// Handle page reloads using sessionStorage 
var sess = sessionStorage.getItem('session-token') 
if(sess && sess !== 'null') { // Sometimes empty values are a string "null" 
    localStorage.setItem('session-token', sess) 
} 

// Set a counter to check when all pages/tabs of the application are closed 
var counter = parseInt(localStorage.getItem('session-counter') || 0, 10) 
counter++ 
localStorage.setItem('session-counter', counter) 

// Event fired when the page/tab is closing 
window.onbeforeunload = function() { 
    var counter = parseInt(localStorage.getItem('session-counter') || 0, 10) 
    counter-- 
    localStorage.setItem('session-counter', counter) 

    // All pages are closed: remove the session token 
    if(counter <= 0) { 
     // Handle page reloads using sessionStorage 
     sessionStorage.setItem('session-token', localStorage.getItem('session-token')) 

     localStorage.removeItem('session-token') 
    } 
} 

有关的localStorage和sessionStorage的更多信息:https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API

为什么不饼干? Cookie不好,原因有两个: 1.它们通常更持久,可在浏览器窗口和选项卡之间共享,即使在浏览器关闭后也可以保留。 2.然而,最重要的是,根据HTTP规范,每次发出请求时都必须将它们发送到Web服务器。如果您设计的应用程序的客户端与API服务器完全分离,您不希望客户端的服务器在任何情况下都看到(或登录)会话令牌。

一些额外的建议:

  1. 会话令牌必须到期。您可以通过将会话令牌存储在服务器上的数据库中并在每个请求上验证它们和/或“签名”它们(以纯文本向令牌添加时间戳,然后添加签名部分(例如HMAC散列)与您只知道秘密密钥编码的时间戳)。
  2. 令牌可以在其生命中多次重复使用。但是,经过一定的秒数后,您可能希望服务器刷新令牌,使旧令牌失效并向客户端发送新令牌。
相关问题