RESTful身份验证

时间:2008-11-26 01:47:30

标签: rest authentication restful-authentication rest-security

RESTful身份验证的含义是什么?它是如何工作的?我无法在Google上找到一个很好的概述。我唯一的理解是你在URL中传递了会话密钥(remeberal),但这可能是错误的。

14 个答案:

答案 0 :(得分:555)

答案 1 :(得分:411)

我怀疑那些热心地喊“HTTP身份验证”的人是否尝试过用REST创建一个基于浏览器的应用程序(而不是机器到机器的Web服务)(没有冒犯的意图 - 我只是觉得他们没有面对过并发症)。

在生成可在浏览器中查看的HTML页面的RESTful服务上使用HTTP身份验证时发现的问题是:

  • 用户通常会获得一个丑陋的浏览器登录框,这对用户不友好。你不能添加密码检索,帮助框等等。
  • 以不同的名称注销或登录是一个问题 - 浏览器将继续向站点发送身份验证信息,直到您关闭窗口
  • 超时很难

一篇非常富有洞察力的文章逐点解决这些问题here,但这会导致浏览器特定的javascript hackery lot ,解决方法的变通方法等等。因此,它也不是向前兼容的,因此在发布新浏览器时需要不断维护。我不认为干净清晰的设计,而且我觉得这是一项额外的工作和头痛,所以我可以热情地向我的朋友展示我的REST徽章。

我相信cookie是解决方案。但等等,饼干是邪恶的,不是吗?不,他们不是,饼干经常使用的方式是邪恶的。 Cookie本身只是一条客户端信息,就像浏览器在浏览时会跟踪的HTTP身份验证信息一样。这条客户端信息在每次请求时都会发送到服务器,就像HTTP身份验证信息一样。从概念上讲,唯一的区别是这个客户端状态的内容可以由服务器确定,作为其响应的一部分。

通过仅使用以下规则使会话成为RESTful资源:

  • 会话将密钥映射到用户ID(可能还有超时的最后操作时间戳)
  • 如果存在会话,则表示该密钥有效。
  • 登录意味着POST到/ sessions,新密钥设置为cookie
  • 注销意味着删除/ sessions / {key}(使用重载的POST,请记住,我们是浏览器,HTML 5还有很长的路要走)
  • 通过在每次请求时将密钥作为cookie发送并检查会话是否存在且有效
  • 来完成身份验证

现在,与HTTP身份验证的唯一区别在于,身份验证密钥由服务器生成并发送给不断发送回来的客户端,而不是客户端从输入的凭据计算它。

converter42补充说,当使用https(我们应该)时,重要的是cookie将设置其安全标志,以便永远不会通过非安全连接发送身份验证信息。好极了,自己没见过。

我认为这是一个运行良好的充分解决方案,但我必须承认,我不足以识别此方案中的潜在漏洞 - 我所知道的是数百个非RESTful Web应用程序使用本质上是相同的登录协议(PHP中的$ _SESSION,Java EE中的HttpSession等)。 cookie头内容仅用于寻址服务器端资源,就像接受语言可能用于访问翻译资源一样,等等。我觉得它是一样的,但也许其他人不一样?伙计们,你觉得怎么样?

答案 2 :(得分:134)

这里的好人已经对这个主题说了足够的话。但这是我的2美分。

有两种互动模式:

  1. 人机对话(HTM)
  2. 机器对机器(MTM)
  3. 机器是共同的标准,表示为REST API,演员/客户端是人或机器。

    现在,在一个真正的RESTful架构中,无状态的概念意味着必须为每个请求提供所有相关的应用程序状态(意味着客户端状态)。相关的是,REST API需要处理请求并提供适当的响应。

    当我们在人机对应用的​​背景下考虑这一点时,基于浏览器的"正如Skrebbel在上面指出的那样,这意味着在浏览器中运行的(web)应用程序需要将其状态和相关信息与其对后端REST API的每个请求一起发送。

    考虑一下:您有一个REST API的数据/信息平台公开资产。也许您有一个处理所有数据立方体的自助BI平台。但是您希望您的(人类)客户通过(1)Web应用程序,(2)移动应用程序和(3)某些第三方应用程序访问此用户。最后,即便是MTM链也会导致HTM - 正确。因此,人类用户仍然处于信息链的顶端。

    在前两种情况下,您有一个人机交互的案例,这个信息实际上是由人类用户消费的。在最后一种情况下,您有一个使用REST API的机器程序。

    身份验证的概念全面适用。您将如何设计此类以便以统一,安全的方式访问REST API?我这样看的方式有两种:

    <强>路-1:

    1. 首先没有登录信息。每个请求都执行登录
    2. 客户端发送其标识参数+特定请求 每个请求的参数
    3. REST API接受它们,转过来,ping用户存储 (不管是什么)并确认认证
    4. 如果auth已建立,请为请求提供服务;否则,否认 使用适当的HTTP状态代码
    5. 对您所有REST API中的每个请求重复上述操作 目录
    6. <强>路-2:

      1. 客户端以身份验证请求开始
      2. 登录REST API将处理所有此类请求
      3. 它接受auth参数(API密钥,uid / pwd或其他任何你 选择)并针对用户存储(LDAP,AD或MySQL DB等)验证auth。
      4. 如果已验证,则创建一个身份验证令牌并将其交还给 客户端/呼叫方
      5. 然后呼叫者发送此身份验证令牌+请求特定参数 对其他业务REST API的每个后续请求,直到注销或直到租约到期为止
      6. 显然,在Way-2中,REST API需要一种方法来识别和信任令牌有效。 Login API执行了auth验证,因此&#34; valet key&#34;需要被目录中的其他REST API信任。

        这当然意味着需要在REST API之间存储和共享身份验证密钥/令牌。这个共享的,可信任的令牌存储库可以是本地/联合的,允许来自其他组织的REST API相互信任。

        但我离题了。

        关键是,&#34;州&#34; (关于客户端的身份验证状态)需要维护和共享,以便所有REST API都可以创建一个信任圈。如果我们不这样做,即Way-1,我们必须接受必须对进入的任何/所有请求执行认证行为。

        执行身份验证是一项资源密集型过程。想象一下,针对每个传入请求,针对您的用户存储执行SQL查询以检查uid / pwd匹配。或者,加密并执行哈希匹配(AWS样式)。从架构上讲,我怀疑每个REST API都需要使用常见的后端登录服务来执行此操作。因为,如果你不这样做,那么你在任何地方都会丢弃auth代码。一团糟。

        层数越多,延迟越多。

        现在,采取Way-1并申请HTM。如果您必须发送uid / pwd / hash或其他任何请求,您的(人类)用户是否真的关心?不,只要你不是每秒都扔掉auth /登录页面就不会打扰她。如果你这样做,祝客户好运。因此,您要做的是将登录信息存储在客户端的某个位置,在浏览器中,在开头,并在每次发出请求时发送。对于(人类)用户,她已经登录,并且#34;会话&#34;是可用的。但实际上,她会根据每个请求进行身份验证。

        与Way-2相同。您的(人类)用户永远不会注意到。所以没有造成任何伤害。

        如果我们将Way-1应用于MTM怎么办?在这种情况下,由于它是一台机器,我们可以通过要求它提交每个请求的认证信息来解决这个问题。没人在乎!在MTM上执行Way-2不会引起任何特殊反应;它是一台该死的机器。它可以少关心!

        所以真的,问题是什么适合你的需要。无国籍状态需要付出代价。付出代价继续前进。如果你想成为一个纯粹主义者,那么也为此付出代价,继续前进。

        最后,哲学并不重要。真正重要的是信息发现,演示和消费体验。如果人们喜欢你的API,你就完成了自己的工作。

答案 3 :(得分:50)

这是一个真正完全RESTful的身份验证解决方案:

  1. 在身份验证服务器上创建公钥/私钥对。
  2. 将公钥分发给所有服务器。
  3. 客户端验证时:

    3.1。发出包含以下内容的令牌:

    • 到期时间
    • 用户名(可选)
    • 用户IP(可选)
    • 密码哈希(可选)

    3.2。使用私钥加密令牌。

    3.3。将加密的令牌发回给用户。

  4. 当用户访问任何API时,他们还必须传递其身份验证令牌。

  5. 服务器可以通过使用auth服务器的公钥对其进行解密来验证令牌是否有效。
  6. 这是无状态/ RESTful身份验证。

    请注意,如果包含密码哈希,用户还会发送未加密的密码以及身份验证令牌。服务器可以通过比较哈希来验证密码是否与用于创建身份验证令牌的密码匹配。使用HTTPS之类的安全连接是必要的。客户端的Javascript可以处理获取用户密码并将其存储在客户端,可以存储在内存中,也可以存储在cookie中,可能使用服务器的公共密钥加密。

答案 4 :(得分:36)

老实说,我在这里看到了很好的答案,但是让我感到困扰的是当有人将整个无状态概念带到一个极端的教条时。它让我想起那些只想拥抱纯粹OO的老Smalltalk粉丝,如果某些东西不是一个对象,那么你做错了。给我一个休息时间。

RESTful方法应该让您的生活更轻松,减少会话的开销和成本,尝试遵循它,因为这是明智的做法,但是你遵循纪律(任何学科/指南)的那一刻如果它不再提供它所预期的好处,那么你做错了。今天一些最好的语言同时具有函数式编程和面向对象。

如果您解决问题的最简单方法是将身份验证密钥存储在Cookie中并通过HTTP标头发送,那么请执行此操作,不要滥用它。请记住,当会话变得笨重时会很糟糕,如果所有会话都包含一个包含密钥的短字符串,那么最重要的是什么?

我愿意接受评论中的更正,但我只是不明白为了避免在我们的服务器中保留一个哈希大词典而让我们的生活变得悲惨(<目前为止)。

答案 5 :(得分:32)

首先,RESTful Web服务是 STATELESS (换句话说, SESSIONLESS )。因此,RESTful服务没有也不应该包含会话或cookie的概念。在RESTful服务中进行身份验证或授权的方法是使用RFC 2616 HTTP规范中定义的HTTP Authorization标头。每个请求都应包含HTTP Authorization标头,并且请求应通过HTTP(SSL)连接发送。这是在HTTP RESTful Web服务中进行身份验证和验证请求授权的正确方法。我已经为Cisco Systems的Cisco PRIME Performance Manager应用程序实现了RESTful Web服务。作为该Web服务的一部分,我也实现了身份验证/授权。

鲁本斯·戈麦斯。

答案 6 :(得分:22)

它当然不是关于“会话密钥”,因为它通常用于指代在REST的所有约束内执行的无会话身份验证。每个请求都是自我描述的,带有足够的信息来自行授权请求,而不需要任何服务器端应用程序状态。

解决此问题的最简单方法是从RFC 2617中的HTTP内置身份验证机制开始。

答案 7 :(得分:15)

非常有洞察力的&#39; @skrebel(http://www.berenddeboer.net/rest/authentication.html)提到的文章 讨论了一种错综复杂但真正破坏的身份验证方法。

您可以尝试访问该页面(仅对经过身份验证的用户可以查看)http://www.berenddeboer.net/rest/site/authenticated.html,无需任何登录凭据。

(抱歉,我无法对答案发表评论。)

我会说REST和身份验证根本不混合。 REST意味着无状态但经过身份验证的“无状态”。是一个国家。你不能将它们放在同一层。如果您是RESTful的拥护者并对国家不满,那么您必须使用HTTPS(即将安全问题留给另一层)。

答案 8 :(得分:12)

我认为restful身份验证涉及将身份验证令牌作为参数传递给请求。例如api使用apikeys。我不相信使用cookies或http auth符合条件。

答案 9 :(得分:12)

2019年2月16日更新

下面提到的方法基本上是“资源所有者密码凭据”授权类型OAuth2.0。这是一种简单的启动和运行方式。但是,通过这种方法,组织中的每个应用程序最终都会拥有自己的身份验证和授权机制。推荐的方法是“授权代码”授权类型。另外,在我之前的回答中,我推荐使用浏览器localStorage来存储身份验证令牌。但是,我开始相信cookie是用于此目的的正确选择。我在this StackOverflow answer中详细说明了我的理由,授权代码授予类型实现方法,安全注意事项等。

我认为以下方法可用于REST服务身份验证:

  1. 创建登录RESTful API以接受用于身份验证的用户名和密码。使用HTTP POST方法可以防止缓存和SSL在传输过程中的安全性 成功验证后,API会返回两个JWT - 一个访问令牌(更短的有效期,比如说30分钟)和一个刷新令牌(更长的有效期,比如说24小时)
  2. 客户端(基于Web的UI)将JWT存储在本地存储中,并且在每个后续API调用中都传递“授权:承载#access令牌”标题中的访问令牌
  3. API通过验证签名和到期日期来检查令牌的有效性。如果令牌有效,请检查用户(它将JWT中的“子”声明解释为用户名)是否可以通过缓存查找访问API。如果用户有权访问API,请执行业务逻辑
  4. 如果令牌过期,则API返回HTTP响应代码400
  5. 客户端在接收400/401时,使用“Authorization:Bearer #refresh token”标头中的刷新令牌调用另一个REST API以获取新的访问令牌。
  6. 在接收带刷新令牌的呼叫时,通过检查签名和到期日期来检查刷新令牌是否有效。如果刷新令牌有效,则从DB刷新用户的访问权限缓存并返回新的访问令牌和刷新令牌。如果刷新令牌无效,则返回HTTP响应代码400
  7. 如果返回新的访问令牌和刷新令牌,请转到步骤2.如果返回HTTP响应代码400,则客户端会认为刷新令牌已过期并要求用户输入用户名和密码
  8. 要注销,请清除本地存储
  9. 通过这种方法,我们每隔30分钟就会执行昂贵的加载缓存操作,其中包含用户特定的访问权限详细信息。因此,如果撤销访问权限或授予新访问权限,则需要30分钟才能反映或注销,然后登录。

答案 10 :(得分:8)

这是做到这一点的方法:Using OAuth 2.0 for Login

只要支持OAuth,您就可以使用Google以外的其他身份验证方法。

答案 11 :(得分:2)

从我的理解中回答这个问题......

使用REST的身份验证系统,您无需实际跟踪或管理系统中的用户。这是通过使用HTTP方法POST,GET,PUT,DELETE来完成的。我们采用这4种方法,并将它们视为数据库交互,如CREATE,READ,UPDATE,DELETE(但在Web上我们使用POST和GET,因为这是锚标记当前支持的)。因此将POST和GET视为我们的CREATE / READ / UPDATE / DELETE(CRUD),然后我们可以在我们的Web应用程序中设计路径,以便推断出我们正在实现的CRUD操作。

例如,在Ruby on Rails应用程序中,我们可以构建我们的Web应用程序,以便如果登录的用户访问http://store.com/account/logout,那么该页面的GET可以被视为用户尝试注销。在我们的rails控制器中,我们将构建一个操作,将用户注销并将其发送回主页。

登录页面上的GET将生成一个表单。登录页面上的POST将被视为登录尝试并获取POST数据并使用它进行登录。

对我来说,这是一种使用映射到其数据库含义的HTTP方法,然后构建一个身份验证系统的做法,记住你不需要传递任何会话ID或跟踪会话。

我还在学习 - 如果你发现任何我说过的错误,请纠正我,如果你了解更多,请将其发回这里。感谢。

答案 12 :(得分:2)

使用公钥基础设施,其中密钥的注册涉及正确的绑定,确保公钥以确保不可否认性的方式绑定到其所分配的个人

http://en.wikipedia.org/wiki/Public_key_infrastructure。如果您遵循正确的PKI标准,则可以识别并锁定不正当使用被盗密钥的人或代理。如果代理需要使用证书,则绑定会非常紧密。一个聪明而快速移动的小偷可以逃脱,但他们会留下更多的碎屑。

答案 13 :(得分:0)

对于保护任何Web应用程序有效的提示

如果要保护应用程序安全,请 然后一定要使用HTTPS而不是HTTP ,这样可以确保在您和用户之间创建安全的通道防止嗅探来回发送给用户的数据,并有助于保持数据交换的机密性。

您可以使用JWT(JSON Web令牌)来保护RESTful APIs ,与服务器端会话相比,它具有很多好处,主要是:

1-具有更高的可扩展性,因为您的API服务器将不必为每个用户维护会话(如果您有很多会话,这可能会是一个沉重的负担)

2- JWT是自包含的,并具有定义用户角色的声明,例如,用户可以访问的权限以及在日期和到期日(之后的JWT无效)发出的权限

3-更易于处理负载平衡器,并且如果您有多个API服务器,则无需共享会话数据,也无需将服务器配置为将会话路由到同一服务器,只要有JWT的请求碰到任何服务器,可以进行身份​​验证和授权

4-减轻了数据库的负担,您不必为每个请求不断存储和检索会话ID和数据

5-如果您使用强键对JWT进行签名,则JWT不会被篡改,因此您可以信任随请求一起发送的JWT中的声明,而不必检查用户会话及其是否为无论是否获得授权,您都可以只检查JWT,然后就可以知道该用户可以做什么和做什么。

许多库提供了使用大多数编程语言创建和验证JWT的简便方法,例如:在node.js中,最受欢迎的一种是jsonwebtoken

由于REST API通常旨在使服务器保持无状态,因此JWT与该概念更加兼容,因为每个请求都是使用自包含的授权令牌发送的(JWT) >与使服务器处于有状态状态以使其记住用户及其角色的会话相比,服务器不必跟踪用户会话,但是,会话也被广泛使用并具有其优点,您可以根据需要进行搜索。

要注意的一件事是,您必须使用HTTPS安全地将JWT交付给客户端,并将其保存在安全的地方(例如,本地存储中)。

您可以了解有关JWT from this link

的更多信息
相关问题