保护REST API / Web服务的最佳做法


828

在设计REST API或服务时,是否存在用于处理安全性(身份验证,授权,身份管理)的最佳实践?

在构建SOAP API时,您以WS-Security为指南,并且有关该主题的文献很多。我发现有关保护REST端点的信息较少。

尽管我了解REST故意没有类似于WS- *的规范,但我希望出现了最佳实践或推荐的模式。

任何讨论或相关文件的链接将不胜感激。如果重要的话,我们将使用WCF和POX / JSON序列化消息,以使用.NET Framework v3.5构建的REST API /服务。


1
您是否知道在github中使用REST API和webServices使用良好模式和实践的任何完整的真实应用程序?
PreguntonCojoneroCabrón

Answers:


298

正如tweakt所说,Amazon S3是一个很好的模型。他们的请求签名确实具有某些功能(例如包含时间戳),可以防止意外和恶意的请求重播。

HTTP Basic的好处是几乎所有HTTP库都支持它。当然,在这种情况下,您将需要SSL,因为通过网络发送纯文本密码几乎是一件坏事。使用SSL时,Basic比Digest更好,因为即使调用者已经知道需要凭据,Digest也需要进行额外的往返来交换现时值。使用Basic,呼叫者只需在第一时间发送凭据即可。

一旦建立了客户端的身份,授权实际上只是一个实现问题。但是,您可以将授权委托给具有现有授权模型的其他组件。再次,关于Basic的好处是,您的服务器最终获得了客户端密码的纯文本副本,您可以根据需要将其简单地传递到基础结构中的另一个组件。


3
SSL是安全性的重要组成部分,但并非所有应用程序都需要该级别的加密。如果有人窃取了您在Twitter上要公开发布的内容,这是否是一个重大缺陷?对于大多数API的SSL加密将是首选。SSL的基础结构要求比纯文本要高一些,并且没有任何中间(基于边缘读取)缓存服务器可以参与重复访问内容的缓存。当心,如果您绝对需要提供的加密功能,则可伸缩性可能会受到影响。
诺曼·H

36
@NormanH:您的论点很糊涂,因为如果有人可以看到我用来发布到Twitter的整个交易,那么他们就可以冒充我并以我的名字发布自己的消息。
Greg Hewgill

3
摘自Wikipedia上的摘要式身份验证,“摘要式访问身份验证是Web服务器可以用来与用户的Web浏览器协商凭据的公认方法之一。它在将密码通过网络发送之前对密码应用哈希功能。比发送纯文本的基本访问身份验证更安全。” 这将是完成我上面提到的内容的一种标准方法。(见en.wikipedia.org/wiki/Digest_access_authentication的细节)
诺曼^ h

5
"sending plaintext passwords over the net is almost universally a bad thing"-您能详细介绍一下“差不多”吗?什么时候是个好主意?
toniedzwiedz 2014年

2
@GregHewgill即使在专用网络中,我也不希望我的用户能够拦截彼此的密码。我能想到的唯一可以通过网络发送密码的情况是用户独自在网络中时。这样的事情在其他地方发生的事实,几乎不是允许它发生的理由。
toniedzwiedz 2014年

115

除HTTP之外,没有其他针对REST的标准。那里已经建立了REST服务。我建议您看一看它们,并了解它们的工作原理。

例如,在开发自己的产品时,我们从Amazon的S3 REST服务中借鉴了很多想法。但是我们选择不使用基于请求签名的更高级的安全模型。更简单的方法是基于SSL的HTTP基本身份验证。您必须决定哪种方法最适合您的情况。

另外,我强烈推荐O'reilly 的书RESTful Web Services。它解释了核心概念,并提供了一些最佳实践。通常,您可以采用他们提供的模型并将其映射到您自己的应用程序。


6
RESTful Web服务绝对是一本好书。必须在此区域阅读。这是彻头彻尾的鼓舞。
EdgarVerona

6
考虑到(1)没有诸如REST规范之类的东西,以及(2)关于体系结构样式和基于网络的软件体系结构设计的论断论文明确提到了REST,@ aehlke收到了如此多的评论意见是怎么回事和6.3中的HTTP:REST应用于HTTP。

20
REST不需要HTTP。
nategood

1
可以从其网站免费获得RESTful Web服务书:crummy.com/writing/RESTful-Web-Services
icc97 '18年

我打算读这本书,然后我意识到这本书主要针对XML格式。考虑到JSON的流行性,我应该使用这本书吗?还是不依赖于数据交换格式。需要指导。
Bhargav Jhaveri

72

您可能还想看看OAuth,这是一种新兴的开放协议,用于基于令牌的授权,专门针对http api。

它与flickr所采取的方法非常相似,请记住牛奶 “休息” api(不一定是静态api的好例子,而是基于令牌的方法的好例子)。


3
但是看来,我认为这里需要的两足式oAuth不如三足式oAuth覆盖(缺乏信息)。
redben 2010年

4
OAuth是关于授权的委派,即我是信息/帐户的所有者,让服务A与我在服务B上的数据进行交互(例如,我让Twitter在我的Facebook上书写)。从广义上讲,这并不是控制用户可以对资源(数据,信息,服务...)执行的授权。这就是XACML介入的地方。XACML使您可以定义有关谁可以执行操作的授权策略。
David Brossard

60

Github上有一个很棒的清单:

认证方式

  • 不要在身份验证,令牌生成,密码存储方面重蹈覆辙。使用标准。

  • Max Retry登录中的使用和监禁功能。

  • 对所有敏感数据使用加密。

JWT(JSON Web令牌)

  • 使用随机的复杂密钥(JWT Secret)使暴力破解令牌变得非常困难。

  • 不要从有效载荷中提取算法。在后端(HS256或RS256)中强制使用算法。

  • 使令牌到期时间(TTLRTTL)尽可能短。

  • 不要在JWT有效负载中存储敏感数据,可以轻松对其进行解码。

OAuth

  • 始终验证redirect_uri服务器端仅允许列入白名单的URL。

  • 始终尝试交换代码而不是令牌(不允许response_type=token)。

  • 将state参数与随机哈希一起使用可防止CSRF进行OAuth身份验证过程。

  • 定义默认范围,并验证每个应用程序的范围参数。

访问

  • 限制请求(限制)以避免DDoS /暴力攻击。

  • 在服务器端使用HTTPS以避免MITM(中间人攻击)

  • HSTS标头与SSL配合使用可避免SSL Strip攻击。

输入项

  • 根据以下操作使用适当的HTTP方法:(GET读取),POST(创建),PUT/PATCH(替换/更新)和DELETE(删除记录),405 Method Not Allowed如果所请求的方法不适用于所请求的资源,则进行响应。

  • 根据要求验证内容类型Accept头(内容协商),只允许你支持的格式(例如application/xmlapplication/json等),响应与406 Not Acceptable响应,如果不匹配。

  • 验证content-type的发布的数据,你接受(例如application/x-www-form-urlencodedmultipart/form-dataapplication/json等)。

  • 验证用户输入以避免常见的漏洞(例如XSS,SQL注入,远程代码执行等)。

  • 请勿在URL中使用任何敏感数据(凭据,密码,安全令牌或API密钥),而应使用标准Authorization标头。

  • 使用API​​网关服务可启用缓存,Rate Limit策略(例如,配额,秒杀,并发速率限制)并动态部署API资源。

处理中

  • 检查所有端点是否在身份验证之后受到保护,以避免破坏身份验证过程。

  • 应避免使用用户自己的资源ID。使用/ me / orders而不是/ user / 654321 / orders。

  • 不要自动增加ID。请改用UUID。

  • 如果要解析XML文件,请确保未启用实体解析,以避免XXE(XML外部实体攻击)。

  • 如果要解析XML文件,请确保未启用实体扩展,以避免通过指数实体扩展攻击引起Billion Laughs / XML炸弹。

  • 使用CDN进行文件上传。

  • 如果您要处理大量数据,请使用Workers和Queues在后台尽可能多地处理并快速返回响应,以避免HTTP阻塞。

  • 不要忘记关闭调试模式。

输出量

  • 发送X-Content-Type-Options: nosniff标题。

  • 发送X-Frame-Options: deny标题。

  • 发送Content-Security-Policy: default-src 'none'标题。

  • 删除指纹头- ,,X-Powered-By 等。ServerX-AspNet-Version

  • 强制content-type响应,如果返回application/json则响应的内容类型为application/json

  • 不要返回敏感数据,例如凭据,密码,安全令牌。

  • 根据完成的操作返回正确的状态码。(例如200 OK400 Bad Request401 Unauthorized405 Method Not Allowed,等等)。


1
不错的列表,尽管有些自以为是-它以无意义的恕我直言开头:“不要使用基本身份验证,请使用标准身份验证(例如JWT,OAuth)。” 您无法获得比Basic Auth更标准的方法,它有它的位置,尤其是对于客户端不是浏览器的API(对于浏览器,JWT通常更适合)。另一方面,OAuth正在使用其他一系列折衷方案进行身份验证,并且实际上无法与Basic Auth和JWT相提并论。
johndodo

你说得对,基本验证使用HTTPS是常见的,但激烈的争论- security.stackexchange.com/questions/988/...。无论如何,我将删除这一点。
Andrejs

43

我很惊讶尚未提及带有客户端证书的SSL。当然,只有当您可以依靠证书标识的用户社区时,这种方法才真正有用。但是许多政府/公司确实将它们发布给用户。用户不必担心会创建另一个用户名/密码组合,并且在每个连接上都建立了身份,因此与服务器的通信可以完全是无状态的,不需要用户会话。(并不意味着提到的任何其他解决方案都需要会话)


实际上,我们确实将此用于某些集成以及加密的vpn隧道,以支持我们无法控制的无法通过https进行通信的旧系统。
凯西2012年

当您需要负载平衡时,客户端证书可能会带来麻烦……可以实现,但不那么直接。
杰里米·洛根

2
@fiXedd-与我相反的是,我对客户端证书的经验是因为它们确实是无状态的。客户端认证的连接可以使用哑负载均衡器进行负载均衡,而不必考虑连接粘性,因为它们要求客户端和服务器之间的共享状态绝对为零。
stinkymatt 2012年

4
哦,您可以做到的。...您可以让负载均衡器转发TCP流量,但是不能(例如)让负载均衡器作为SSL的终止点。
杰里米·洛根

如果客户端证书及其根权限是自签名的,它仍然安全吗?根权限将被导入到客户端的受信任的根证书颁发机构中。
乔伊斯

38

这些答案中的每个人都忽略了真正的访问控制/授权。

例如,如果您的REST API / Web服务与发布/获取病历有关,则您可能需要定义关于谁可以访问数据以及在什么情况下可以访问数据的访问控制策略。例如:

  • 医生可以获取与其有护理关系的患者的病历
  • 没有人可以在工作时间以外发布医疗数据(例如9到5)
  • 最终用户可以获取自己拥有的医疗记录或监护人的医疗记录
  • 护士可以更新与护士属于同一单位的患者的病历。

为了定义和实现那些细粒度的授权,您将需要使用一种称为XACML的基于属性的访问控制语言,即可扩展访问控制标记语言。

这里的其他标准适用于以下方面:

  • OAuth:ID。联盟和授权委派,例如让某项服务代表我代表另一项服务(Facebook可以发布到我的Twitter)
  • SAML:身份联盟/ Web SSO。SAML与用户身份有关。
  • WS-Security / WS- *标准:这些标准着重于SOAP服务之间的通信。它们特定于应用程序级消息传递格式(SOAP),并且涉及消息传递的各个方面,例如可靠性,安全性,机密性,完整性,原子性,事件性...没有一个涉及访问控制,并且都特定于SOAP。

XACML与技术无关。它可以应用于Java应用程序,.NET,Python,Ruby ... Web服务,REST API等。

以下是有趣的资源:


2
我不明白为什么您不能仅实施将获得用户及其权限的令牌系统,而令牌系统本质上是同一件事?
斯坦(Stan)2013年

您可以采用基于令牌的方法。这也很好用,但是您仍然需要逻辑来定义用户获得哪些权限,换句话说,就是将哪些权限插入令牌中。这就是XACML可以帮助您实现的目标。这也避免了令牌膨胀。
David Brossard 2014年

2
附带说明一下,“ 9到5”对安全有何贡献?好像攻击者仅在夜间活动?更不用说严重的使用含义了,就好像医生只工作“ 9到5”一样。
罗兰

这是医疗保健方案中的常见要求。例如查看HL7。万一医生在工作时间以外需要接诊,也有破玻璃的情况。对于黑客来说,一旦一切都变了
David Brossard

1
我的一些同事确实对此进行了调查。谢谢@SimplyG。
大卫·布罗萨德

25

我使用过OAuth几次,还使用了其他一些方法(BASIC / DIGEST)。我全力建议OAuth。以下链接是我使用OAuth看到的最好的教程:

http://hueniverse.com/oauth/guide/


尽管这是关于OAuth 1.0的非常老的答案,但值得注意的是,您引用的链接的作者对OAuth 2.0的说法是这样的“我得出的结论是,OAuth 2.0是一个不良协议...与OAuth相比在1.0中,2.0规范更加复杂,互操作性差,实用性差,不完整,最重要的是安全性降低。” 。明确地说,我引用的评论是在您发布答案数年后做出的。
skomisa

17

关于Rain的安全性方面,我见过的最好的帖子之一已于1 RainDrop结束。MySpace API还将OAuth用于安全性,您可以在RestChess代码中完全访问其自定义渠道,对此我进行了很多研究。这是在Mix上演示的,您可以在此处找到发布内容。


感谢链接(1 RainDrop)-关于与SOAP v REST相关的安全性的非常有趣的讨论
Nathan

15

感谢您的出色建议。我们最终使用了自定义HTTP标头将身份令牌从客户端传递到服务,以准备将RESTful API与即将推出的Microsoft Zermatt Identity框架集成。我所描述的问题,在这里和我们的解决方案在这里。我还接受了tweakt的建议,并购买了RESTful Web服务 -如果您要构建任何类型的RESTful API,这是一本非常不错的书。


1
这种方法对我来说听起来很可疑。是什么阻止攻击者使用身份令牌伪装客户端?我上次检查时HTTPS不会保护URL或标头...
Gili

2
嗯...不确定你是对的。我相信,除了需要了解几种加密方式所需的几个头文件以外,其他所有头文件都已加密。
弥敦道

51
那是错的。HTTPS保护一切。它去了:TCP握手... TLS握手... <ENCRYPTED> GET / foo 200 OK ...拆卸</ ENCRYPTED>。
Mark Renouf

1
请注意,您还可以将令牌作为cookie传递(而不是自定义标头)。这在浏览器中表现良好,因为它在大多数工具箱和应用程序中使用具有标准行为的HTTP标头。在服务方面,cookie不必与会话相关,您可以使用它来传达所需的任何令牌。
布鲁斯·奥尔德森,

11
Wayback Machine很漂亮:问题描述解决方案
cjc343



6

我搜索了很多有关宁静的ws安全性的信息,最后,我们还使用了从cookie到客户端到服务器的cookie通过令牌来验证请求。我将spring security用于服务中请求的授权,因为我必须根据DB中已经存在的指定安全策略对每个请求进行身份验证和授权。


6

SOAP世界已经被安全标准很好地覆盖了,但这并不意味着它在默认情况下是安全的。首先,标准非常复杂。复杂性不是安全和实现漏洞(例如XML签名包装攻击)的好朋友在这里很普遍。

而对于.NET环境我也不会有多大效果,但“与Java构建Web服务”(与〜10个作者砖)确实帮助了我很多理解WS- *安全架构,特别是它的怪癖。


4

REST本身不提供安全标准,但是OAuth和SAML之类的东西正迅速成为该领域的标准。但是,身份验证和授权只是您需要考虑的一小部分。与Web应用程序有关的许多已知漏洞都非常适用于REST api。您必须考虑输入验证,会话破解,不适当的错误消息,内部员工漏洞等。这是一个大课题。


4

我要添加(与stinkeymatt一致),最简单的解决方案是将SSL证书添加到您的站点。换句话说,请确保您的网址是HTTPS://。这将涵盖您的运输安全(物有所值)。使用RESTful url的目的是保持简单(与WS *安全/ SAML不同),您可以使用oAuth2 / openID connect甚至是Basic Auth(在简单情况下)。但是您仍然需要SSL / HTTPS。请在此处检查ASP.NET Web API 2的安全性:http : //www.asp.net/web-api/overview/security(文章和视频)


3

由于@Nathan最后是一个简单的HTTP标头,因此有人说OAuth2和客户端SSL证书。要点是……您的REST API不必处理安全性,因为它实际上不在API的范围之内。

相反,无论是在Web代理后面的HTTP标头(SiteMinder,Zermatt甚至Apache HTTPd等常见方法)还是OAuth 2一样复杂,都应在其上面放置一个安全层。

关键是请求应该在没有任何最终用户交互的情况下工作。所有需要做的就是确保对REST API的连接进行身份验证。在Java EE中,我们有一个userPrincipal可以在上获得的概念HttpServletRequest。还可以在部署描述符中管理URL模式是安全的,因此REST API代码不再需要检查。

在WCF世界中,我将ServiceSecurityContext.Current用来获取当前的安全上下文。您需要配置您的应用程序以要求认证。

我上面的陈述有一个例外,那就是使用随机数来防止重播(这可能是攻击,也可能是某人两次提交相同的数据)。该部分只能在应用程序层中处理。


3

对于Web应用程序安全性,您应该查看OWASP(https://www.owasp.org/index.php/Main_Page),其中提供了各种安全攻击的备忘单。您可以采用尽可能多的措施来保护您的应用程序。关于API安全性(授权,身份验证,身份管理),已经提到了多种方法(基本,摘要和OAuth)。OAuth1.0中存在漏洞,因此您可以使用OAuth1.0a(出于对规范的考虑,OAuth2.0未被广泛采用)


2

已经有一段时间了,但是问题仍然很重要,尽管答案可能有所改变。

API网关将是一种灵活且高度可配置的解决方案。我测试并使用了KONG相当多,非常喜欢我所看到的。KONG提供了自己的admin REST API,可用于管理用户。

Express-gateway.io是更新的,并且也是API网关。

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.