.net - RESTful 身份验证。客户端无状态身份验证

标签 .net rest authentication .net-4.5 c#-5.0

我正在为某些开发实现一组 RESTful 服务,其中一个是 认证服务 .

认证服务验证两种身份:

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

  • 这些 RESTful 服务 无国籍 .

    当客户端应用程序针对 进行身份验证时认证服务 ,或者当人或机器使用凭据验证身份时,两种操作都会生成 AppToken 用户 token 分别。

    这些 token 是加盐哈希,因此对 RESTful 基础架构的后续请求将在不共享 AppKey 和凭据的情况下进行身份验证。

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

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

    客户端如何交互地取消身份验证? 刚刚删除客户端安全状态 .如果是 Web 客户端,它会丢弃身份验证 cookie 并刷新页面,客户端检测到没有身份验证 cookie 并且用户被重定向到登录页面。

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

    我不打算列出无状态服务的优点,因为我绝对确定这种方法是可行的,但我发现了一个问题:无状态认证/未认证意味着客户端不通知服务器他们关闭他们的 session ,因此安全存储以大量无用记录结束 .

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

    有一些方法可以解决这种情况:
  • 每当服务层收到请求时,它都会更新 token 到期日期,因此自动化过程可能会丢弃那些已到期的 token ,定义 token 的任意到期时间(例如 24 小时) .
  • 妥协架构的无状态特性,让客户端通知服务层他们不想再进行身份验证,因此服务可以将关联的 token 丢弃到客户端 session (但是等等……如果客户端关闭 Web 客户端会发生什么?用户永远不会主动通知服务必须丢弃 token ……所以……僵尸 token 已经存在,所以自动化过程应该丢弃它们,但是。 .. 什么是僵尸 token ? 我不喜欢这种方法 )。
  • 完全无状态的身份验证,没有存储,每个请求的身份验证。

  • 这就是问题!您建议的方法是什么 - 即使它不是 1.、2. 或 3. - 为什么?

    感谢您阅读这么长的文章——老实说,我相信这个问题的结论对任何人都非常有用——!

    最佳答案

    第三

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

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

  • 目的:
    客户端 C 希望与服务 S 通话。
  • 客户端 C 发送其共享 secret 或公钥 PKC用于对服务 A 进行身份验证,C 知道服务 A 的端点和公钥( PKA )。
  • A [now + interval | user-id or PKC]SA -> C
    解释:

    服务 A 将一个间隔添加到当前日期/时间作为到期。在要发送的缓冲区中现在是到期日期和用户 ID,PKC (假设您有一个有效的身份提供者)。
    [now + interval | user-id or PKC] = T
    A 签名;
    [T]SA
  • 客户端 C 希望与后端服务 S 通话。
  • C [[M|[T]SA]SC -> S
    C 将消息 M 加上它从 A 签名的 token 发送到服务 S。
  • S 关心 C 真的发送它并验证 C 的签名 SC它从信封中读取。

    S 验证签名 SA token 。失败意味着请求被拒绝。

    S 验证 token [T]SA : 用户 ID/PKC正确和 token 日期 >= 现在。 token 过期意味着向客户端 C 发送“ token 已过期”消息。如果 token 签名错误,则权限被拒绝。

    (可选;S 授权 C,题外话)
  • S 执行工作并返回 [M2]SS给客户 C。

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

    证书

    问题' C# Sign Data with RSA using Bouncy Castle ' 显示您如何签署和验证一段字符串,即您发送的消息。

    你需要证书;如果您使用的是配置管理器(您应该这样做!;)),例如 puppet,那么您 create a certificate signing request (CSR)然后 sign it using puppet .

    Post Scriptum 尤其是未经身份验证

    有一种叫做证书撤销请求的东西,它基本上是一个已被撤销且不被信任/使用的公钥的 list 。地点 PKC在那里广播撤销,它基本上通过要求客户端进行另一轮证书签名请求来起作用。

    此外,如果您希望能够使特定 token 过期,请将唯一 ID (UUID/GUID) 添加到 token T当您创建它时,并有一个 token 撤销列表,在更改时类似地广播,您可以在 token UUID 过期时清除它们。因此,如果接收到的 T 在其中,服务也会检查 token 撤销列表。

    基于哈希的 token

    看看软件巨头都在做什么。例如。 Amazon 的 REST 接口(interface),使用共享 key :

    The Amazon S3 REST API uses a custom HTTP scheme based on a keyed-HMAC (Hash Message Authentication Code) for authentication. To authenticate a request, you first concatenate selected elements of the request to form a string. You then use your AWS Secret Access Key to calculate the HMAC of that string. Informally, we call this process "signing the request," and we call the output of the HMAC algorithm the "signature" because it simulates the security properties of a real signature. Finally, you add this signature as a parameter of the request, using the syntax described in this section.



    Read more on Amazon's scheme.

    上面的颠覆/攻击向量
  • 我最初描述的方案需要 SSL,它容易受到众多证书颁发机构的攻击,as well as a number of other things .
  • 您很容易受到重放攻击,即中间人重新发送消息。如果您的 REST 接口(interface)是幂等的,那么您就是安全的。如果向请求添加服务器已知的加密随机数,您也是安全的。
  • 关于.net - RESTful 身份验证。客户端无状态身份验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12174393/

    相关文章:

    java - REST GET API 调用期间的字符编码

    javascript - 通过 Azure AD 身份验证进行单点登录 (SSO) 时出错 - AADSTS50059

    c# - 一个Windows服务中的多个服务进程(System.ServiceProcess.ServiceBase)

    api - RESTful api 设计、HATEOAS 和资源发现

    c# - .Net 中带有希伯来字母和数字的 Unicode 字符串

    java - 请求 Web API 的 GET 方法

    mysql - 作为 MySQL root 用户 : how to switch to other user without password

    java - 为什么我的方法没有收到我的 boolean 值?

    c# - 在 C# 应用程序中处理位图

    c# - 测试中的代码覆盖率