保护REST API / Web服务的最佳实践

时间:2008-08-11 05:44:43

标签: wcf security rest authorization rest-security

在设计REST API或服务时,是否有任何已建立的处理安全性的最佳实践(身份验证,授权,身份管理)?

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

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

非常感谢任何讨论或相关文件的链接。 如果重要,我们将使用带有POX / JSON序列化消息的WCF用于使用.NET Framework v3.5构建的REST API /服务。

17 个答案:

答案 0 :(得分:290)

正如tweakt所说,亚马逊S3是一个很好的模型。他们的请求签名确实有一些功能(例如合并时间戳),有助于防止意外和恶意请求重放。

HTTP Basic的优点在于几乎所有HTTP库都支持它。当然,在这种情况下,您需要使用SSL,因为通过网络发送明文密码几乎是一件坏事。使用SSL时,Basic优于Digest,因为即使调用者已经知道需要凭据,Digest也需要额外的往返来交换nonce值。使用Basic,呼叫者只需在第一次发送凭证。

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

答案 1 :(得分:113)

除了HTTP之外,没有REST标准。那里有成熟的REST服务。我建议你看看他们,并了解他们的工作方式。

例如,我们在开发自己的S3 REST服务时借用了很多想法。但我们选择不使用基于请求签名的更高级安全模型。更简单的方法是基于SSL的HTTP Basic身份验证。你必须决定什么在你的情况下最有效。

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

答案 2 :(得分:72)

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

它与flickrremember the milk“rest”apis采用的方法非常相似(不一定是restful apis的好例子,但是基于令牌的方法的好例子)。

答案 3 :(得分:48)

Github上有一个很棒的核对清单:

<强>验证

  • 不要在身份验证,令牌生成,密码存储中重新发明轮子。使用标准。

  • 在登录中使用Max Retry和jail功能。

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

JWT(JSON网络令牌)

  • 使用随机复杂的密钥(JWT Secret)来强制执行令牌非常困难。

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

  • 让令牌过期(TTLRTTL)尽可能短。

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

<强>的OAuth

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

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

  • 使用带有随机哈希的state参数来阻止CSRF身份验证过程中的OAuth

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

使用

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

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

  • 使用带有SSL的HSTS标头来避免SSL Strip攻击。

输入

  • 根据操作使用正确的HTTP方法:GET(读取),POST(创建),PUT/PATCH(替换/更新)和{{1} }(删除记录),如果请求的方法不适合所请求的资源,则使用DELETE进行响应。

  • 根据请求405 Method Not Allowed标题(内容协商)验证内容类型,以仅允许您支持的格式(例如Acceptapplication/xml等)并使用{{1如果不匹配则回复。

  • 在接受时验证发布数据的application/json(例如406 Not Acceptablecontent-typeapplication/x-www-form-urlencoded等。

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

  • 请勿在网址中使用任何敏感数据(凭据,密码,安全令牌或API密钥),但请使用标准multipart/form-data标题。

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

<强>处理

  • 检查所有端点是否受到身份验证后的保护,以避免身份验证过程中断。

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

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

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

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

  • 使用CDN进行文件上传。

  • 如果您正在处理大量数据,请使用工作人员和队列在后台尽可能多地处理并快速返回响应以避免HTTP阻塞。

  • 不要忘记关闭 DEBUG 模式。

<强>输出

  • 发送Authorization标题。

  • 发送Rate Limit标题。

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

  • 删除指纹标题 - X-Frame-Options: denyContent-Security-Policy: default-src 'none'X-Powered-By等。

  • 强制Server为您的回复,如果您返回X-AspNet-Version,则回复内容类型为content-type

  • 请勿返回凭据,密码,安全令牌等敏感数据。

  • 根据完成的操作返回正确的状态代码。 (例如application/jsonapplication/json200 OK400 Bad Request等。

答案 4 :(得分:43)

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

答案 5 :(得分:37)

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

例如,如果您的REST API / Web服务是关于POSTing / GETing医疗记录,您可能需要定义访问控制策略,了解谁可以访问数据以及在何种情况下。例如:

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

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

此处的其他标准如下:

  • OAuth:id。联邦和授权授权,例如让服务代表我的另一项服务(Facebook可以发布到我的Twitter)
  • SAML:身份联合/网络SSO。 SAML非常关注用户是谁。
  • WS-Security / WS- *标准:这些标准专注于SOAP服务之间的通信。它们特定于应用程序级消息传递格式(SOAP),它们处理消息传递的各个方面,例如可靠性,安全性,机密性,完整性,原子性,事件...没有覆盖访问控制,所有都是SOAP特有的。

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

以下是有趣的资源:

答案 6 :(得分:25)

我曾经使用过OAuth几次,还使用了其他一些方法(BASIC / DIGEST)。我全心全意地建议OAuth。以下链接是我在使用OAuth时看到的最佳教程:

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

答案 7 :(得分:17)

我在安全方面遇到的关于REST的最好的帖子之一就是1 RainDrop。 MySpace API也使用OAuth来保证安全性,并且您可以完全访问RestChess代码中的自定义通道,我对此进行了大量探索。这是在Mix上演示的,你可以找到帖子here

答案 8 :(得分:15)

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

答案 9 :(得分:14)

OWASP(开放式Web应用程序安全项目)有一些备忘单,涵盖了Web应用程序开发的所有方面。该项目是非常有价值和可靠的信息来源。 关于REST服务,您可以查看:https://www.owasp.org/index.php/REST_Security_Cheat_Sheet

答案 10 :(得分:7)

我会推荐OAuth 2/3。您可以在http://oauth.net/2/

找到更多信息

答案 11 :(得分:6)

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

答案 12 :(得分:6)

SOAP世界很好地涵盖了安全标准这一事实并不意味着默认情况下它是安全的。首先,标准非常复杂。复杂性不是安全性的好朋友,而XML signature wrapping attacks等实施漏洞在这里很常见。

至于.NET环境,我帮不了多少,但是“Building web services with Java”(一个有~10位作者的砖块)确实帮助我很多了解WS- *安全架构特别是它的怪癖。

答案 13 :(得分:4)

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

答案 14 :(得分:4)

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

答案 15 :(得分:2)

由于@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来获取当前的安全上下文。您需要将应用程序配置为要求身份验证。

我上面的语句有一个例外,那就是使用nonce来防止重放(可能是攻击或只是两次提交相同数据的人)。该部分只能在应用层中处理。

答案 16 :(得分:2)

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