保护 REST API/Web 服务的最佳实践 [已关闭]

Best Practices for securing a REST API / web service [closed]

提问人:Nathan 提问时间:8/11/2008 最后编辑:Jakub KubrynskiNathan 更新时间:7/5/2023 访问量:316740

问:


想改进这个问题吗?更新问题,以便可以通过编辑这篇文章用事实和引文来回答。

5年前关闭。

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

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

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

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

WCF 授权 REST-安全性

评论

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

答:

119赞 Mark Renouf 8/11/2008 #1

除了 HTTP 之外,没有其他 REST 标准。那里有成熟的REST服务。我建议你看一看它们,感受一下它们是如何工作的。

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

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

评论

6赞 EdgarVerona 1/10/2009
RESTful Web Services 绝对是一本很棒的书。这方面的必读之作。这真是鼓舞人心。
6赞 4/15/2012
考虑到 (1) 没有 REST 规范这样的东西,以及 (2) 关于架构风格和基于网络的软件架构设计的 Fielding Dissertation 在 6.3 中明确提到了 REST 和 HTTP:REST 应用于 HTTP,为什么@aehlke获得了如此多的赞成票。
22赞 nategood 5/17/2013
HTTP 不是 REST 的必需条件。
3赞 icc97 6/5/2018
RESTful Web Services 一书可从他们的网站免费获得:crummy.com/writing/RESTful-Web-Services
1赞 yolob 21 5/31/2019
REST 功能未与数据格式耦合
303赞 Greg Hewgill 8/11/2008 #2

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

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

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

评论

3赞 Norman H 1/2/2013
SSL 是安全性的重要组成部分,但并非所有应用程序都需要该级别的加密。如果有人在运输途中窃取了您将在 Twitter 上公开发布的内容,这是一个如此显着的缺点吗?对于大多数API的SSL加密将是首选。SSL 的基础结构要求略高于纯文本,并且没有中间(在此处阅读基于边缘)缓存服务器可以参与重复访问内容的缓存。请注意,如果您绝对需要提供的加密,您的可扩展性可能会受到影响。
36赞 Greg Hewgill 1/2/2013
@NormanH:你的论点是似是而非的,因为如果有人能看到我用来发布到Twitter的整个交易,那么他们就可以冒充我,以我的名义发布他们自己的信息。
3赞 Norman H 1/3/2013
引用维基百科关于摘要式身份验证的话,“摘要式访问身份验证是 Web 服务器可用于与用户的 Web 浏览器协商凭据的商定方法之一。它在通过网络发送密码之前将哈希函数应用于密码,这比发送明文的基本访问身份验证更安全。(详见 en.wikipedia.org/wiki/Digest_access_authentication
6赞 toniedzwiedz 5/29/2014
"sending plaintext passwords over the net is almost universally a bad thing"- 你能详细说明一下“几乎”吗?什么时候不是一个坏主意?
2赞 toniedzwiedz 5/29/2014
@GregHewgill即使在专用网络中,我也不希望我的用户能够拦截彼此的密码。我能想到的唯一情况是,当用户独自一人在网络中时,可以通过网络发送密码。这种事情发生在其他地方的事实几乎不是允许它的理由。
15赞 Nathan 9/18/2008 #3

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

评论

1赞 Gili 10/4/2008
这种方法对我来说听起来很可疑。什么可以防止攻击者使用身份令牌伪装客户端?HTTPS 不保护我上次检查的 URL 或标头......
2赞 Nathan 10/30/2008
嗯......不确定你是否正确。我相信,除了了解需要哪种加密所需的少数标头外,所有其他标头都是加密的。
52赞 Mark Renouf 2/4/2009
这是错误的。HTTPS保护一切。它说:TCP握手...TLS 握手...<加密>获取 /foo 200 OK...拆解</加密>。
1赞 Bruce Alderson 11/11/2011
请注意,您还可以将令牌作为 cookie(而不是自定义标头)传递。这在浏览器中表现良好,因为它使用具有大多数工具包和应用程序中标准行为的 HTTP 标头。在服务方面,cookie不必与会话相关,您可以使用它来传达所需的任何令牌。
11赞 cjc343 10/24/2012
Wayback Machine 是一件美丽的事情:问题描述解决方案
74赞 John Spurlock 9/18/2008 #4

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

它与 flickr 所采用的方法非常相似,并记住 milk “rest” api(不一定是 restful API 的好例子,但基于令牌的方法的好例子)。

评论

3赞 redben 11/11/2010
但似乎我认为这里需要的 2 条腿的 oAuth 没有像 3 条腿那样被覆盖(缺乏信息)。
4赞 David Brossard 9/25/2013
OAuth 是关于授权的,即我作为信息/帐户的所有者,让服务 A 与我在服务 B 上的数据进行交互(例如,我让 Twitter 在我的 facebook 上写字)。它不是广义上的授权,而是控制用户可以对资源(数据、信息、服务等)执行的操作。这就是 XACML 的用武之地。XACML 允许您定义有关谁可以执行哪些操作的授权策略。
17赞 degnome 9/19/2008 #5

我遇到过的关于安全性的最好的帖子之一,因为它与 REST 相关,在 1 RainDrop 结束。MySpace API 也使用 OAuth 来确保安全性,您可以在 RestChess 代码中完全访问它们的自定义通道,我对此进行了大量探索。这是在 Mix 上演示的,您可以在此处找到帖子。

评论

0赞 Nathan 10/14/2008
感谢您的链接 (1 RainDrop) - 非常有趣的安全讨论,因为它与 SOAP 与 REST 有关
26赞 Rob Ottaway 1/10/2009 #6

我使用过几次 OAuth,还使用过一些其他方法(BASIC/DIGEST)。我全心全意地推荐 OAuth。以下链接是我见过的关于使用 OAuth 的最佳教程:

OAuth 1.0 指南 |Hueniverse的

评论

1赞 skomisa 1/23/2019
虽然这是一个非常古老的关于 OAuth 1.0 的答案,但值得注意的是,你引用的链接的作者对 OAuth 2.0 是这样说的:“我得出的结论是 OAuth 2.0 是一个糟糕的协议......与 OAuth 1.0 相比,2.0 规范更复杂、互操作性更差、有用性更差、更不完整,最重要的是安全性更低。需要明确的是,我引用的评论是在您发布答案几年后发表的。
2赞 Nae 12/7/2021
链接似乎已断开,仅供参考。
0赞 Tom Newton 7/3/2023
自 2016 年左右起就过时了,请参阅 web.archive.org 上的 oit 存档
43赞 stinkymatt 9/26/2009 #7

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

评论

0赞 Casey 9/5/2012
实际上,我们确实将其用于某些集成以及加密的 vpn 隧道,以支持我们无法控制的无法通过 https 通信的旧系统。
0赞 Jeremy Logan 10/16/2012
当您需要负载平衡时,客户端证书可能会带来麻烦......这是可以做到的,但就不那么简单了。
2赞 stinkymatt 10/16/2012
@fiXedd - 与此相反,我使用客户端证书的经验恰恰相反,因为它们确实是无状态的。客户端证书身份验证的连接可以使用哑负载平衡器进行负载平衡,而不考虑连接粘性,因为它们要求客户端和服务器之间的共享状态绝对为零。
4赞 Jeremy Logan 10/20/2012
哦,你可以做到......您可以只让负载均衡器转发 TCP 流量,但不能让负载均衡器作为 SSL 的终止点。
0赞 Joyce 3/19/2015
如果客户端证书及其根证书颁发机构是自签名的,它是否仍然安全?根证书颁发机构将导入到客户端的受信任根证书颁发机构中。
6赞 Parisa Kachoui 5/15/2012 #8

我搜索了很多关于 restful ws 安全性的信息,我们最终还通过 cookie 从客户端到服务器使用令牌来验证请求。我使用 Spring Security 对服务中的请求进行授权,因为我必须根据数据库中已有的指定安全策略对每个请求进行身份验证和授权。

5赞 Robert Morschel 10/12/2012 #9

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

7赞 Abhijit Gaikwad 3/14/2013 #10

我会推荐 OAuth 2/3。您可以在 http://oauth.net/2/ 找到更多信息

评论

8赞 Butifarra 3/21/2013
仔细说明一下,为什么你会推荐版本 2,而它仍然在很大程度上不完整?恕我直言,对于大多数应用程序来说,1.0a 版仍然是一个可靠的解决方案。
40赞 David Brossard 9/25/2013 #11

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

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

  • 医生可以获取与他们有护理关系的患者的病历
  • 没有人可以在执业时间之外(例如朝九晚五)发布医疗数据
  • 最终用户可以获取他们拥有的医疗记录或他们作为监护人的患者的医疗记录
  • 护士可以更新与护士属于同一单位的患者的病历。

为了定义和实现这些细粒度的授权,您需要使用一种基于属性的访问控制语言,称为 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 12/31/2013
我不明白为什么你不能只实现令牌系统来获得用户和他的权限,这本质上是一回事?
0赞 David Brossard 1/2/2014
您可以采用基于令牌的方法。这也很好用,但你仍然需要定义用户获得哪些权限的逻辑,换句话说,在令牌中插入哪些权限。这就是 XACML 可以帮助您实现的目标。它还避免了令牌膨胀。
2赞 Roland 7/11/2016
顺便说一句,“朝九晚五”对安全性有什么贡献?好像攻击者只在晚上活跃?更不用说严重的使用影响,就好像医生只“朝九晚五”工作一样。
0赞 David Brossard 7/11/2016
这是医疗保健方案中的常见要求。例如,查看 HL7。如果医生确实需要在下班时间以外访问,也有一些打破玻璃的情况。至于黑客,一旦他们加入,所有的赌注都落空了
1赞 David Brossard 5/9/2018
我的一些同事确实正在对此进行调查。谢谢@SimplyG。
7赞 kravietz 11/21/2013 #12

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

至于 .NET 环境,我不会有太大帮助,但是“使用 Java 构建 Web 服务”(一个有 ~10 个作者的砖块)确实对我理解 WS-* 安全架构,尤其是它的怪癖有很大帮助。

14赞 WelsonJR 2/25/2014 #13

OWASP(Open Web Application Security Project)有一些备忘单,涵盖了 Web 应用程序开发的所有方面。这个项目是一个非常有价值和可靠的信息来源。 关于REST服务,您可以检查以下内容: https://www.owasp.org/index.php/REST_Security_Cheat_Sheet

5赞 Manish Jain 3/1/2014 #14

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

4赞 Archimedes Trajano 7/17/2014 #15

@Nathan最终得到了一个简单的 HTTP 标头,有些人说 OAuth2 和客户端 SSL 证书。它的要点是这样的......您的 REST API 不应该处理安全性,因为这实际上应该超出 API 的范围。

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

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

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

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

4赞 java_geek 10/6/2014 #16

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

2赞 Matt Bannert 8/12/2017 #17

已经有一段时间了,但这个问题仍然很重要,尽管答案可能已经发生了一些变化。

API 网关将是一个灵活且高度可配置的解决方案。 我测试和使用了KONG很多,真的很喜欢我所看到的。KONG 提供了自己的管理 REST API,您可以使用它来管理用户。

Express-gateway.io 是较新的,也是一个 API 网关。

74赞 Andrejs 11/9/2017 #18

在 Github 上有一个很好的清单:

认证

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

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

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

JWT(JSON Web 令牌)

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

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

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

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

OAuth的

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

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

  • 使用带有随机哈希的 state 参数来防止身份验证过程。CSRFOAuth

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

访问

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

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

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

输入

  • 根据操作使用正确的 HTTP 方法:(读取)、(创建)、(替换/更新)和(删除记录),如果请求的方法不适合请求的资源,则进行响应。GETPOSTPUT/PATCHDELETE405 Method Not Allowed

  • 验证请求标头上的 content-type(内容协商)以仅允许支持的格式(例如 、 等),如果不匹配,则使用响应进行响应。Acceptapplication/xmlapplication/json406 Not Acceptable

  • 在您接受时验证发布的数据(例如、、等)。content-typeapplication/x-www-form-urlencodedmultipart/form-dataapplication/json

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

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

  • 使用 API Gateway 服务启用缓存、策略(例如配额、峰值阻止、并发速率限制)并动态部署 API 资源。Rate Limit

加工

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

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

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

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

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

  • 使用 CDN 上传文件。

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

  • 不要忘记关闭 DEBUG 模式。

输出

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

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

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

  • 删除指纹标头 - 、 等。X-Powered-ByServerX-AspNet-Version

  • 强制响应,如果返回,则响应内容类型为 。content-typeapplication/jsonapplication/json

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

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

评论

1赞 johndodo 12/25/2017
不错的列表,虽然有点固执己见 - 它以一个胡说八道的恕我直言开头:“不要使用基本身份验证使用标准身份验证(例如 JWT、OAuth)。你不能得到比基本身份验证更标准的 y,它有它的位置,特别是对于客户端不是浏览器的 API(对于浏览器,JWT 通常更合适)。另一方面,OAuth 使用一组其他折衷方案进行身份验证,并不能真正与基本身份验证和 JWT 相提并论。
1赞 Andrejs 12/29/2017
你是对的,带有 HTTPS 的 BasicAuth 很常见,但它引起了激烈的争论 - security.stackexchange.com/questions/988/......无论如何,我都会删除这一点。