REST API中基于令牌的身份验证

时间:2016-03-29 01:30:59

标签: spring rest security spring-security resteasy

我尝试实现基于令牌的身份验证方法:

  1. 每次成功登录都会创建新令牌。

  2. 如果用户选择“保持登录状态”或用户正在使用移动设备,则令牌将保留在Redis数据库中而不会过期。否则,令牌将在20分钟后过期。

  3. 用户通过身份验证后,会在我的Redis数据库中的每个后续请求中检查令牌。

  4. 我想知道如何识别设备。对于移动设备,我可以使用设备标识符。但是如何识别浏览器呢?

    示例:用户使用Chrome登录并选择“让我登录”。使用Redis中的浏览器名称生成并保留令牌。如果用户从Firefox登录,则将令牌和“Firefox”保存在数据库中。我在Redis中保存令牌,而在成功验证时创建令牌。是否可以仅使用令牌和使用令牌的浏览器?或者我是否也需要保留IP?

    其他问题:如何避免攻击者从cookie中窃取令牌?

2 个答案:

答案 0 :(得分:20)

基于令牌的身份验证的工作原理

简而言之,基于令牌的身份验证方案遵循以下步骤:

  1. 客户端将其凭据(用户名和密码)发送到服务器。
  2. 服务器验证凭据并生成令牌。
  3. 服务器将先前生成的令牌与用户标识符和到期日期一起存储在某个存储中。
  4. 服务器将生成的令牌发送给客户端。
  5. 在每个请求中,客户端都会将令牌发送到服务器。
  6. 服务器在每个请求中从传入请求中提取令牌。使用令牌,服务器查找用户详细信息以执行身份验证和授权。
    1. 如果令牌有效,则服务器接受请求。
    2. 如果令牌无效,则服务器拒绝该请求。
  7. 服务器可以提供端点来刷新令牌。
  8. 如何将凭据发送到服务器

    在REST应用程序中,从客户端到服务器的每个请求都必须包含服务器要理解的所有必要信息。有了它,您不依赖于存储在服务器上的任何会话上下文,也不会破坏Roy T. Fielding在stateless constraint中定义的REST架构的dissertation

      

    5.1.3 Stateless

         

    [...]从客户端到服务器的每个请求必须包含理解请求所需的所有信息,并且不能利用服务器上任何存储的上下文。因此,会话状态完全保留在客户端上。 [...]

    访问需要身份验证的受保护资源时,每个请求必须包含所有必要的数据才能进行正确身份验证/授权。这意味着将对每个请求执行身份验证

    请查看RFC 7235关于新身份验证方案注意事项的引用:

      

    5.1.2. Considerations for New Authentication Schemes

         

    HTTP身份验证框架的某些方面   对新身份验证方案的工作方式施加限制:

         
        
    • HTTP认证被认为是无状态的:所有的   必须提供验证请求所需的信息   在请求中,而不是依赖于服务器记住   先前的请求。 [...]
    •   

    身份验证数据(凭据)应属于标准HTTP Authorization标头。来自RFC 7235

      

    4.2. Authorization

         

    Authorization标头字段允许用户代理进行身份验证   本身与原始服务器 - 通常,但不一定,后   收到401(未经授权)回复。它的价值包括   包含用户身份验证信息的凭据   代理请求的资源领域。

         
    Authorization = credentials
    
         

    [...]

    请注意,此HTTP标头的名称很不幸,因为它带有身份验证数据而不是授权。无论如何,这是发送凭据的标准标题。

    执行基于令牌的身份验证时,令牌是您的凭据。在此方法中,您的硬凭证(用户名和密码)将交换为在每个请求中发送的令牌。

    令牌是什么样的

    身份验证令牌是服务器生成的一段数据,用于标识用户。基本上,令牌可以是 opaque (除了值本身之外没有显示任何细节,如随机字符串)或者可以自包含(喜欢 JSON Web Token ):

    • 随机字符串:可以通过生成随机字符串并将其持久保存到具有过期日期且与其关联的用户标识符的数据库来发出令牌。

      < / LI>
    • JSON网络令牌(JWT):由RFC 7519定义,它是在双方之间安全地表示声明的标准方法。 JWT是一个独立的令牌,使您能够在有效负载中存储用户标识符,到期日期和任何您想要的内容(但不要存储密码),这是{{3编码为JSON。客户端可以读取有效负载,并且可以通过验证服务器上的签名来轻松检查令牌的完整性。如果您不需要跟踪JWT令牌,则不需要坚持使用JWT令牌。尽管如此,通过持久存在令牌,您将有可能使其无效并撤销其访问权限。要保持跟踪JWT令牌,而不是保留整个令牌,您可以保留令牌标识符(Base64声明)和一些元数据(您发出令牌的用户,到期日期等),如果您需要。要找到一些与JWT合作的优秀资源,请查看jti

    提示:始终考虑删除旧令牌,以防止数据库无限期增长。

    如何接受令牌

    永远不会接受您的应用程序未发布的过期令牌或令牌。如果您使用的是JWT,则必须检查令牌签名。

    请注意,一旦您发出令牌并将其交给您的客户,您就无法控制客户端对令牌的处理方式。 无法控制严重

    检查http://jwt.io标头字段以告知正在使用哪个浏览器访问您的API是一种常见做法。但是,值得一提的是,HTTP标头可以轻松欺骗,您应该从不信任您的客户。浏览器没有唯一标识符,但如果您愿意,可以获得良好的User-Agent级别。

    我不了解您的安全要求,但您始终可以在服务器中尝试以下操作来增强API的安全性:

    • 检查用户在发出令牌时使用的浏览器。如果以下请求中的浏览器不同,则只需拒绝令牌。
    • 在发出令牌时获取客户端远程地址(即客户端IP地址),并使用第三方API查找客户端位置。例如,如果以下请求来自其他国家/地区的地址,则拒绝令牌。要按IP地址查找位置,您可以尝试免费的API,例如fingerprintingMaxMind GeoLite2。请注意,为API收到的每个请求命中第三方API并不是一个好主意,并且可能会对性能造成严重损害。但是,您可以通过存储客户端远程地址及其位置来最小化缓存的影响。现在有一些缓存引擎可用。仅举几例:IPInfoDBGuavaInfinispanEhcache

    通过网络发送敏感数据时,您最好的朋友是HTTPS,它可以保护您的应用免受Spring的攻击。<​​/ p>

    顺便问一下,我提到过你永远不要相信你的客户吗?

答案 1 :(得分:0)

一旦服务器从客户端收到请求,它就包含User-Agent。此属性将帮助我们识别客户端。

请参阅此链接:How do I detect what browser is used to access my site?