REST API 设计:GET 需要不应存储在 Web 服务器日志中的敏感参数
REST API Design: GET requires sensitive parameters that should not be stored in web server logs
我正在设计一个(as-RESTful-as-possible)API,想知道您如何最好地解决以下问题:
- 假设我们正在设计一个 TLS 端点来检索一些资源:
GET /objects/{id}
- 我们不希望对象
{id}s
存储在我们的网络服务器日志中,因此我们希望避免使用查询字符串或 URI 参数;这在请求正文中留下了参数。 (假设数据是这样的 id 是敏感的,我们无权访问另一个非敏感的 id)
- 我了解建议不要在 GET 请求正文中包含参数。
- 我知道不建议使用 POST 获取数据,因为它更倾向于 RPC 设计风格并且通常可能会造成混淆。
我们如何(应该)设计 API GET
端点以避免使用可以记录的查询或 URI 参数?
在这种情况下使用POST是否可以接受,或者有其他创造性的方法吗?
(注意:此 API 不会暴露给第三方)
如果您使用 Apache 作为您的网络服务器,您可以使用 CustomLog to remove/replace the sensitive values, this answer 提供了一个示例脚本。
一般来说,如果您坚持使用 REST,则应将标识符保留在 URL 路径中(例如 /objects/{id}
)并坚持使用 GET
HTTP 方法,但我很理解你正在努力解决的问题。如果这个 ID 在某种程度上是秘密的,那么关闭这个神奇的秘密 ID 的记录绝对是个好主意。也就是说,您遇到的问题可能表明您的 API 存在更大的设计问题,而阻止日志记录可能无法解决更大的问题。
例如,这是 "security by obscurity"(例如,ID 是一个秘密,任何知道它的人都可以访问数据)?或者只是保护敏感信息(例如,PII,如美国社会安全号码的 ID)?在这两种情况下,使用此值作为标识符可能不是一个好主意。
如果此 ID 本身是敏感的,则可能值得为每个资源生成一个随机标识符,然后开始传递它。 Google Cloud 对项目(ID 与编号)执行此操作,如 aip.dev/2510 中所述。请注意他们如何明确声明 third-parties 无法使用项目 ID,并且将始终在不透明的项目 "number" 作为标识符上运行。
如果这是模糊的安全性,那么您可能需要某种身份验证/授权令牌或 GET 请求中的 header,从 RESTful 的角度来看应该没问题。这意味着某人可以获取秘密标识符,因为如果没有其他一些凭据,它就毫无用处。
我肯定会警告不要将您的 HTTP 方法切换到 POST 只是为了避免记录敏感内容。在长期 运行 中,这将导致从事该项目的新员工感到困惑,并阻止您使用任何对 API.
做出 RESTful 假设的工具。
我认为有很多服务都面临着想要保护敏感标识符的问题。然而,即使这个问题已经有几年了,我也没有找到合适的解决方案。
所提供的解决方案只是简单地改变您的网络服务器的日志记录并不像已经提到的那样完美,但也忽略了这样一个事实,即每个客户端在使用您的 API 时都应该做同样的事情(其中可能JavaScript 客户端,通过代理,在浏览器中...祝你好运)
我知道的解决方案是:
正在加密参数;但这会使您的 API 更加复杂,并且需要加密密钥。
使用伪ID,如@jj-geewax所述;然而,这可能比加密 (1) 更复杂,因为您必须为每个敏感参数实例交换一个伪 ID:
- 客户端在其对服务器的请求中使用伪ID发起,服务器比向客户端请求来解析伪ID! (所以客户端也应该有一个端点!)
- 客户端 POSTS 对服务器的敏感 ID,它收到一个伪 ID,它可以在对此 ID 的请求中使用它
- 客户端和服务器已经通过其他方式预先交换了伪ID
POST body中的参数,同时请求数据;这不是 REST
- 可选择使用 X-HTTP-Method-Override 使您实际请求数据的应用程序更加明确。
解决方案 3 似乎是迄今为止实施最多的 simple/easiest 方法,尽管它违反了 REST 设计规则。但我很想听听替代方法或其他见解。
更新:OWASP 对请求中的敏感参数做了如下说明
Sensitive information in HTTP requests
RESTful web services should be careful to prevent leaking credentials. Passwords, security tokens, and API keys should not appear in the URL, as this can be captured in web server logs, which makes them intrinsically valuable.
- In POST/PUT requests sensitive data should be transferred in the request body or request headers.
- In GET requests sensitive data should be transferred in an HTTP Header.
这可能比使用 (POST) 主体有点困难,但在了解如何实现 REST 时也很不错。
我正在设计一个(as-RESTful-as-possible)API,想知道您如何最好地解决以下问题:
- 假设我们正在设计一个 TLS 端点来检索一些资源:
GET /objects/{id}
- 我们不希望对象
{id}s
存储在我们的网络服务器日志中,因此我们希望避免使用查询字符串或 URI 参数;这在请求正文中留下了参数。 (假设数据是这样的 id 是敏感的,我们无权访问另一个非敏感的 id) - 我了解建议不要在 GET 请求正文中包含参数。
- 我知道不建议使用 POST 获取数据,因为它更倾向于 RPC 设计风格并且通常可能会造成混淆。
我们如何(应该)设计 API GET
端点以避免使用可以记录的查询或 URI 参数?
在这种情况下使用POST是否可以接受,或者有其他创造性的方法吗?
(注意:此 API 不会暴露给第三方)
如果您使用 Apache 作为您的网络服务器,您可以使用 CustomLog to remove/replace the sensitive values, this answer 提供了一个示例脚本。
一般来说,如果您坚持使用 REST,则应将标识符保留在 URL 路径中(例如 /objects/{id}
)并坚持使用 GET
HTTP 方法,但我很理解你正在努力解决的问题。如果这个 ID 在某种程度上是秘密的,那么关闭这个神奇的秘密 ID 的记录绝对是个好主意。也就是说,您遇到的问题可能表明您的 API 存在更大的设计问题,而阻止日志记录可能无法解决更大的问题。
例如,这是 "security by obscurity"(例如,ID 是一个秘密,任何知道它的人都可以访问数据)?或者只是保护敏感信息(例如,PII,如美国社会安全号码的 ID)?在这两种情况下,使用此值作为标识符可能不是一个好主意。
如果此 ID 本身是敏感的,则可能值得为每个资源生成一个随机标识符,然后开始传递它。 Google Cloud 对项目(ID 与编号)执行此操作,如 aip.dev/2510 中所述。请注意他们如何明确声明 third-parties 无法使用项目 ID,并且将始终在不透明的项目 "number" 作为标识符上运行。
如果这是模糊的安全性,那么您可能需要某种身份验证/授权令牌或 GET 请求中的 header,从 RESTful 的角度来看应该没问题。这意味着某人可以获取秘密标识符,因为如果没有其他一些凭据,它就毫无用处。
我肯定会警告不要将您的 HTTP 方法切换到 POST 只是为了避免记录敏感内容。在长期 运行 中,这将导致从事该项目的新员工感到困惑,并阻止您使用任何对 API.
做出 RESTful 假设的工具。我认为有很多服务都面临着想要保护敏感标识符的问题。然而,即使这个问题已经有几年了,我也没有找到合适的解决方案。
所提供的解决方案只是简单地改变您的网络服务器的日志记录并不像已经提到的那样完美,但也忽略了这样一个事实,即每个客户端在使用您的 API 时都应该做同样的事情(其中可能JavaScript 客户端,通过代理,在浏览器中...祝你好运)
我知道的解决方案是:
正在加密参数;但这会使您的 API 更加复杂,并且需要加密密钥。
使用伪ID,如@jj-geewax所述;然而,这可能比加密 (1) 更复杂,因为您必须为每个敏感参数实例交换一个伪 ID:
- 客户端在其对服务器的请求中使用伪ID发起,服务器比向客户端请求来解析伪ID! (所以客户端也应该有一个端点!)
- 客户端 POSTS 对服务器的敏感 ID,它收到一个伪 ID,它可以在对此 ID 的请求中使用它
- 客户端和服务器已经通过其他方式预先交换了伪ID
POST body中的参数,同时请求数据;这不是 REST
- 可选择使用 X-HTTP-Method-Override 使您实际请求数据的应用程序更加明确。
解决方案 3 似乎是迄今为止实施最多的 simple/easiest 方法,尽管它违反了 REST 设计规则。但我很想听听替代方法或其他见解。
更新:OWASP 对请求中的敏感参数做了如下说明
Sensitive information in HTTP requests
RESTful web services should be careful to prevent leaking credentials. Passwords, security tokens, and API keys should not appear in the URL, as this can be captured in web server logs, which makes them intrinsically valuable.
- In POST/PUT requests sensitive data should be transferred in the request body or request headers.
- In GET requests sensitive data should be transferred in an HTTP Header.
这可能比使用 (POST) 主体有点困难,但在了解如何实现 REST 时也很不错。