如何在RESTful Web服务中实现登录?


78

我正在构建带有服务层的Web应用程序。服务层将使用RESTful设计构建。这种想法是,将来我们可能会构建使用与Web应用程序相同的服务层的其他应用程序(iPhone,Android等)。我的问题是-如何实现登录?我认为我无法从较传统的基于动词的设计过渡到基于资源的设计。如果我是用SOAP构建的,则可能会有一个称为Login的方法。在REST中,我应该有一个资源。我很难理解如何为登录构建URI。应该是这样的:

http:// myservice / {用户名}?p = {密码}

编辑:前端Web应用程序使用传统的ASP.NET框架进行身份验证。但是,在身份验证过程中的某个时刻,我需要验证提供的凭据。在传统的Web应用程序中,我将进行数据库查找。但是在这种情况下,我将调用服务而不是进行数据库查找。因此,我在服务中需要一些可以验证提供的凭据的东西。而且,除了验证提供的凭据外,在用户成功通过身份验证后,我可能还需要有关用户的某种信息-例如其全名,其ID等。我希望这可以使问题更清楚。

还是我没有考虑正确的方法?我觉得我很难正确地描述我的问题。

科里

Answers:


62

正如S.Lott所指出的,我们这里有两方面的内容:登录和身份验证

身份验证不在这里讨论,因为对此进行了广泛的讨论并且存在共识。但是,客户端实际上需要针对RESTful Web服务进行身份验证的实际条件是什么?是的,某种令牌,我们称它为访问令牌。

客户端)因此,我所需要的只是一个访问令牌,但是如何获得这种RESTful?
服务器)为什么不简单地创建它?
客户)怎么了?
服务器)对我来说,访问令牌就是资源。因此,我将为您创建一个,以换取您的用户名和密码。

因此,服务器可以提供资源URL“ / accesstokens”,用于将用户名和密码发布到POST,将链接返回到新创建的资源“ / accesstokens / {accesstoken}”。或者,您返回包含访问令牌和带有资源链接的href的文档:

<访问令牌
  id =“ {访问令牌ID在这里;例如GUID}”
  href =“ / accesstokens / {id}”
/>

最有可能的是,您实际上并未将访问令牌创建为子资源,因此不会在响应中包含其href。
但是,如果这样做,客户端可以代表它生成链接吗?没有!
请记住,真正的RESTful Web服务将资源链接在一起,使客户端可以自行导航而无需生成任何资源链接。

您可能要问的最后一个问题是,是否应将用户名和密码以HTML形式或文档(例如XML或JSON)发布-这取决于... :-)


4
并非完全遵循REST,但比其他方法简单且可衡量的更好。再加上很好的幽默感。
特德·约翰逊

2
帕特里克(Patrick),您提出的答案与此相同吗?stackoverflow.com/a/1135995/14731
吉利2014年

用户名和/或密码不匹配时,403状态代码是否正确?
2015年

好主意 创建“ accesstoken”资源。
分拣机2015年

25

您没有“登录”。您“验证”。差异世界。

您有很多身份验证方法。

HTTP基本,摘要,NTLM和AWS S3身份验证

  • HTTP基本和摘要身份验证。这使用HTTP_AUTHORIZATION标题。这非常好,非常简单。但是会导致大量的流量。

  • 用户名/签名认证。有时称为“ ID和KEY”身份验证。这可以使用查询字符串。

    ?username=this&signature=some-big-hex-digest

    这就是像亚马逊这样的地方。用户名是“ id”。“密钥”是摘要,类似于用于HTTP摘要身份验证的摘要。双方必须就摘要进行协商以继续进行。

  • 某种基于cookie的身份验证。 例如,可以将OpenAM配置为代理,以进行身份​​验证并提供一个RESTful Web服务器可以使用的cookie。客户端将首先进行身份验证,然后为cookie提供每个RESTful请求。


2
@ S.Lott @Corey用户绝对可以与RESTful系统进行交互。大多数静态HTML网站都是RESTful“服务”。
Darrel Miller

7
@达雷尔·米勒(Darrel Miller):“您的想法……有缺陷”没有提供适当的上下文或任何有用的东西。这是消极的,没有太大的帮助。
S.Lott

5
@达雷尔·米勒(Darrel Miller):“声称REST仅限于...简直荒谬”。随你。而是重复出现错误的内容,您能否解释正确的内容?您能否提供简单的肯定陈述而不是否定陈述?您能解释一下REST是什么吗?并非有无数的事物。
S.Lott

4
@达雷尔·米勒(Darrel Miller):5.2.1.2表示似乎很清楚。您的评论是非常负面的。您能否提供正面的修正或更新,而不是负面的看法?我无法弄清楚如何纠正或修改我的答案以使您满意,因为您所做的只是说我在某种程度上“有缺陷”或“传播不正确的信息”或“荒谬”。什么是瑕疵少,错误少或荒谬?
S.Lott

5
@ S.Lott 1)用户一直与RESTful系统进行交互。2)HTML是RESTful系统返回的完全有效的媒体类型。3)REST不是HTTP的子集。REST是一种体系结构样式,HTTP是一种协议。4)RESTful系统不限于“ Web服务”。5)RESTful系统可以使用某种形式的授权令牌来模拟登录,而不会遇到与会话有关的问题。
Darrel Miller

1

好问题,提出了。我真的很喜欢帕特里克的回答。我用类似的东西

-/用户/ {用户名} /登录会话

随着POST和GET被处理。因此,我使用凭证发布了一个新的登录会话,然后可以通过GET将当前会话视为资源。

该资源是一个登录会话,并且可能具有访问令牌或授权码,有效期等。

奇怪的是,由于MVC站点是API的客户端,因此我的MVC调用者本身必须通过标头提供密钥/承载者令牌,以证明其有权尝试创建新的登录会话。

编辑

我认为这里的其他一些答案和评论正在通过带外共享机密解决此问题,并且仅通过标头进行身份验证。在许多情况下或服务到服务的呼叫都很好。

另一种解决方案是传递令牌,OAuth或JWT或其他方式,这意味着“登录”已经由另一个进程(可能是基于POST表单的浏览器中的常规登录UI)进行了。

我的答案是针对位于该UI后面的服务的,假设您希望将登录和身份验证以及用户管理放置在REST服务中而不是站点MVC代码中。它是用户登录服务。

它还允许其他服务“登录”并获得到期令牌,而不是使用预共享密钥以及CLI或Postman中的测试脚本。


2
是,将令牌传递到标头中。将其作为URL的一部分传递,不。使用HTTPS时,URL在传输过程中被加密。然而; 该URL也存储在浏览器历史记录和服务器日志中。有很多充分的理由避免在URL查询参数中传递对安全敏感的数据。
Craig 2015年

0

自2011年以来发生了很大的变化...

如果您愿意使用第三方工具,并且对于Web UI稍微偏离REST,请考虑http://shiro.apache.org

Shiro基本上为您提供了一个用于身份验证和授权的servlet过滤器。您可以使用@ S.Lott列出的所有登录方法,包括基于表单的简单身份验证。

过滤其余需要身份验证的URL,Shiro将完成其余工作。

我目前正在自己​​的项目中使用它,到目前为止,它对我来说效果很好。

人们可能会对这感兴趣 。https://github.com/PE-INTERNATIONAL/shiro-jersey#readme


0

关于REST的第一件事是基于Token的资源访问,与传统方式不同,基于令牌验证授予访问权限。简单来说,如果您拥有正确的令牌,就可以访问资源。现在,还有很多其他东西可以用于令牌创建和操作。

对于第一个问题,您可以设计一个Restfull API。凭据(用户名和密码)将传递到您的服务层。然后,服务层将验证这些凭据并授予令牌。凭据可以是简单的用户名/密码,也可以是SSL证书。SSL证书使用OAUTH协议,更加安全。

您可以像这样设计您的URI-用于令牌请求的URI-> http:// myservice / some-directory / token?(您可以在此URI中为令牌传递Credentilals)

要使用此令牌进行资源访问,可以将此[Authorization:Bearer(令牌)]添加到您的http标头中。

客户可以使用此令牌访问服务层的不同组件。您也可以更改此令牌的有效期限以防止滥用。

对于第二个问题,您可以做的一件事是,您授予不同的令牌来访问服务层的不同资源组件。为此,您可以在令牌中指定资源参数,并基于此字段指定许可。

您也可以通过以下链接获取更多信息 -http://www.codeproject.com/Articles/687647/Detailed-Tutorial-for-Building-ASP-NET-WebAPI-REST

http://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api


-4

我以前也遇到过同样的问题。登录不能很好地转换为基于资源的设计。

我通常的处理方式是拥有登录资源,并在参数字符串上传递用户名和密码,基本上是

http:// myservice / login?u = {username}&p = {password}上获取

响应是某种会话或身份验证字符串,然后可以将其传递给其他API进行验证。

在登录资源上进行GET的另一种方法是进行POST,REST纯粹主义者现在可能现在不喜欢我:),并传递主体中的凭据。响应将是相同的。


11
密码?纯文本密码?作为查询字符串?您是真的意思吗,还是您的密码摘要?
S.Lott

谢谢。那讲得通。这是一个后续问题-对于大型应用程序,您会为所有内容创建一个大型RESTful服务还是将其分解为其他服务?我当时在考虑只为身份验证提供服务,然后为我的应用程序的不同模块提供不同的服务。是否有任何理由为什么您会或不会这样做?
Corey Burnett

3
S. Lott:这取决于您要执行的操作。当然,如果您可以进行摘录,那么一定可以。有时,摘要是不可能的。如果向您开放的唯一选项是发送纯文本密码,请通过SSL进行操作,在这种情况下,最好使用POST而不是GET来防止浏览器记住您发送的内容。
Alex

Corey:我不确定我是否理解一种大型Web服务与许多不同Web服务之间的区别。通常,您根据资源来定义服务,添加的数量尽可能少。我想我虽然错过了你的意思。
Alex

亚历克斯:假设我的Web应用程序有四个不同的主要部分-报告,订单,下载和发票。拥有4个不同的服务定义或只有1个服务定义有意义吗?有什么特定的原因为什么您不想将其分解为许多不同的服务?
Corey Burnett
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.