代码之家  ›  专栏  ›  技术社区  ›  Matías Fidemraizer

RESTful身份验证。客户端,无状态未验证

  •  5
  • Matías Fidemraizer  · 技术社区  · 13 年前

    我正在为一些开发实现一组RESTful服务,其中之一是 身份验证服务

    身份验证服务 验证两种身份:

    • 应用程序 基于AppKey的身份验证,因此客户端必须注册密钥才能访问其余服务
    • 用户 众所周知的基于凭据(用户+密码)的用户身份验证,因此人类和机器可以通过客户端应用程序使用这些RESTful服务。

    这些RESTful服务 无国籍的

    当客户端应用程序根据 身份验证服务 ,或者当人或机器使用凭据验证为身份时,这两个操作都会生成 应用令牌 户令牌 分别地

    这些令牌是一个咸散列,因此对RESTful基础设施的后续请求将在不共享的情况下进行身份验证 应用程序密钥 资格证书

    从完全无状态方法的角度来看,这些令牌不应存储在服务层中的任何位置,而应存储在某种客户端状态下(例如,Web客户端将使用 HTTP cookie )。 这就是我当前实现的工作方式

    因为使用这些重新验证每个请求 代币 并让服务层接收来自客户端的令牌,以便进行比较 什么令牌来自客户端 检查它是否是在服务层中重新生成的有效令牌,并将其与客户端拥有的令牌进行比较 太贵了,我已经实现了一个服务层 应用令牌 户令牌 ,都具有到期日期和所有者(为其创建令牌的应用程序或用户),以便检查来自客户端的令牌是否存在于令牌存储中。

    客户端如何以交互方式取消身份验证? 正在删除客户端安全状态 。如果是Web客户端,它会丢弃身份验证cookie,只刷新页面,客户端不会检测到身份验证cookie并且用户会重定向到登录页面。

    从RESTful服务的角度来看, 这是无状态的未认证 :客户不知道 戏法 具有服务层伪认证状态。 这只是一个服务实现细节——一个性能优化。

    我不打算列出 专业人士 因为我绝对相信这种方法是可行的,但我发现了一个问题: 无状态身份验证/未身份验证意味着客户端不会通知服务器他们关闭了会话,因此安全存储以大量无用的记录结束

    如果服务客户的会话时间有限(例如,每天1小时、3小时…),那么这不是一个大问题,但是 如果用户必须经过身份验证会发生什么 永远(8个月,一年) ? 你如何区分 什么是过期代币?

    有一些方法可以解决这种情况:

    1. 每当服务层接收到请求时,它都会更新令牌到期日期,因此自动过程可以丢弃那些已经到期的令牌,这些令牌定义了令牌的任意到期(例如24小时)

    2. 折衷体系结构的无状态性质,让客户端通知服务层他们不想再进行身份验证,这样服务就可以将关联的令牌丢弃到客户端会话中 ( 但是等等。。。如果客户端关闭Web客户端会发生什么?用户永远不会主动通知服务必须删除令牌。。。所以…僵尸代币还存在,所以自动化过程应该删除它们,但是。。。什么是僵尸代币? 我不喜欢这种方法 )

    3. 完全无状态身份验证,无存储,按请求身份验证。

    这就是问题所在!你建议的方法是什么——即使不是1.,2。或3.-为什么?

    感谢您的长时间阅读-我真诚地相信这个问题的结论将对任何人都非常有用-!

    2 回复  |  直到 13 年前
        1
  •  7
  •   Community Mohan Dere    9 年前

    第三个

    无状态身份验证,基于令牌。假设传输级别加密。

    • [X]S S --X由S的公钥签名
    • [X|Y] --X和Y在同一个信封中
    • Y [M]S Y -> S --Y向S发送签名消息M。

    目标: 客户C希望与服务S通话。

    1. 客户端C发送其共享密钥或公钥 PK C 用于对服务A进行身份验证,C知道其端点和公钥( PK A )。

    2. A [now + interval | user-id or PK C ]S A -> C

      解释如下:

      服务A在当前日期/时间上添加一个间隔作为过期时间。在要发送的缓冲器中现在是到期日期和用户id, PK公司 C (假设您拥有有效的身份提供程序)。

      [now + interval | user-id or PK C ] = T

      A在上面签名;

      [T]S A

    3. 客户端C希望与后端服务S对话。

    4. C [[M|[T]S A ]S C -> S

      C向服务S发送消息M加上它从A获得签名的令牌。

    5. S关心C是否真的发送了它,并验证了C的签名 S C 它是从信封上读出来的。

      S验证签名 S A 的代币。失败意味着请求被拒绝。

      S验证令牌 [T] 秒 A. :用户id/ PK公司 C 正确且标记日期>=现在Expired token表示向客户端C发送“token Expired”消息。如果token签名错误,则拒绝权限。

      (可选;S授权C,离题)

    6. S执行工作并发送回 [M 2 ]S S 至客户C。

    这不会是太多的开销;验证签名是一项非常快速的操作。

    证书

    问题' C# Sign Data with RSA using Bouncy Castle '显示了如何对正在发送的消息进行签名和验证。

    你需要证书;如果你正在使用配置管理器(你应该这样做!;)),就像木偶一样,那么你 create a certificate signing request (CSR) 然后 sign it using puppet

    在上发布脚本 未经认证 特别是

    有一种叫做 证书吊销请求 ,基本上是已撤回且不可信任/使用的公钥的列表。位置 PK公司 C 然后广播撤销,它基本上是通过要求客户端再做一次 证书签名请求 圆形的

    此外,如果您想要特定的过期功能 代币 ,将唯一ID(UUID/GGUID)添加到令牌 T 当你创建它时 令牌吊销列表 ,类似地在更改时广播,即在令牌UUID过期时清除它们。因此,服务也会检查 令牌吊销列表 如果接收到的T在其中。

    基于哈希的令牌

    看看软件巨头们在做什么。例如,使用共享密钥的亚马逊REST接口:

    Amazon S3 REST API使用基于keyed-HMAC的自定义HTTP方案 (哈希消息身份验证代码)进行身份验证。进行身份验证 一个请求,首先将请求的选定元素连接到 形成一个字符串。然后使用您的AWS密钥进行计算 该字符串的HMAC。非正式地,我们将此过程称为“签署 请求,”我们将HMAC算法的输出称为“签名” 因为它模拟了真实签名的安全属性。 最后,使用添加此签名作为请求的参数 本节中描述的语法。

    Read more on Amazon's scheme.

    上面的子版本/攻击向量

    • 我所描述的方案最初需要SSL,它很容易受到众多证书颁发机构的攻击, as well as a number of other things
    • 你很容易受到重播攻击,即中间的人重新发送消息。如果您的REST接口 幂等的 你很安全。如果您添加一个已知加密的服务器,您也是安全的 随机数 响应请求。
        2
  •  -1
  •   Matías Fidemraizer    13 年前

    选择的方法:完全无状态认证和未认证

    最后,我得出了一个结论 协议 以便切换到整个完全无状态的基于令牌的认证和未认证。

    如何实现?

    首先,这就是应用程序需要的无状态基于令牌的身份验证(但用户身份验证的工作方式相同,不包括此清单):

    • 申请注册系统。应用程序是对您的服务的访问。这是“你的应用程序访问网络上的一些服务(内联网、互联网、云…)。这是在创建 应用程序密钥 (跳过此项进行用户身份验证)。
    • 服务器证书,以便使用HTTPS/SSL对客户端到服务的连接进行加密。

    这是验证应用程序的流程:

    1. 客户端向身份验证服务发送身份验证请求。此请求必须包括 应用程序密钥(AppKey)

    2. 身份验证服务接收以前发送的请求。

    3. 现在,身份验证服务创建 应用程序令牌 (AppToken),它是必要信息的自描述串联,用于跟踪具体的经过身份验证的客户端到依赖于身份验证服务的服务。

    4. 应用令牌 是复合字符串( 该组合可以是使用JSON序列化的对象 )第页,共页:

      • 一个应用程序散列(*a SHA-或其他-这是连接一些应用程序信息的结果。这是信息将是服务机密+ 到期日期 (这是令牌本身的一部分)。 为什么是截止日期? 。想象一下,中间人或其他人可以破坏安全并修改令牌的过期时间?当加密的令牌被解密以验证请求时,再次散列到期日+AppKey的结果将不再产生相同的散列,因此令牌将无效。
      • 发布日期 。创建令牌时的当前UTC日期+时间。
      • 到期日期 。一个UTC日期T+时间,在该时间令牌将不再有效。
    5. 身份验证服务对步骤#4的结果(JSON序列化对象)进行加密**使用AppKey作为对称密码的密钥或密码。在我的情况下,我会使用Rijndael。

    6. 后续请求将包括此令牌,以避免发送纯文本凭据。这些请求将始终包括 应用程序密钥 同样,身份验证服务将能够识别哪个应用程序正在尝试对请求进行身份验证。

    7. 一段时间后,令牌过期或无效,客户端请求新的AppToken。或者客户端被用户关闭,并且没有可以保存安全令牌的持久存储,所以下一个客户端会话将在需要时请求新的令牌。


    关于.NET实现这种身份验证方法的一些提示和细节:

    • 我用过 System.Security.Cryptography.RijndaelManaged 类进行对称加密。AppKey和AppToken(在基于令牌的用户身份验证的情况下,它几乎是相同的解决方案)都是使用 RijndaelManaged

    • 加密后的文本将转换为十六进制字符串。这是与身份验证响应一起发送的。在我们的示例(RESTFul API)中,HEX字符串表示 应用令牌 将作为响应标头发送。每当请求包含此HEX字符串时,身份验证过程都会将其重新转换为原始加密文本,稍后会对其进行解密,以评估令牌是否有效。


    感谢Henrik的努力。我在你自己的回答中采纳了一些概念,并将它们与我自己的结论混合在一起。

    推荐文章