在REST API调用中输入密码


31

假设我有一个REST API,该API也用于设置/重置密码。我们还假设它可以通过HTTPS连接工作。是否有充分的理由不将该密码放在调用路径中,也可以说我将在BASE64中对它进行编码?

一个示例是重设这样的密码:

http://www.example.com/user/joe/resetpassword/OLDPASSWD/NEWPASSWD

我知道BASE64没有加密,但是在这种情况下,我只想保护密码以进行网上冲浪。


61
您是否建议对GET产生副作用?那是违反协议的地方。
Esben Skov Pedersen

27
这不是真正的REST,因为resetpassword/OLDPASSWD/NEWPASSWD它不是资源。这是对流程的调用。您无需将所有内容填充到URL中。
usr

5
@Esben:谁说这是GET?OP从未这么说过。
dagnelies 2015年

3
是的,他没有问题。但是他对Netch的回答的评论是“猜想我毕竟必须使用POST”,因此我们可以假定他最初打算/询问GET。正如埃斯本指出的那样,这是一件坏事。GET应该是只读的。
Mawg

4
这篇有见地的文章解释了密码重置机制的许多陷阱,可能有助于更好地了解这种情况。
9000

Answers:


76

好的服务器记录发送给它的所有请求,包括URL(通常,“?”之后没有可变部分),源IP,执行时间...您是否真的希望此日志(可能由大量管理员读取)包含非常安全的信息作为密码?Base64并不是阻止他们前进的绊脚石。


42
这不是使用POST的最大原因。这是安全原因。但是正如Esben在评论中已经指出的那样,使用GET更改状态违反了这种Rest服务
Pinoniq 2015年

2
@BartFriederichs:浏览器的历史记录会记住该URL。并通过制作一个包含要尝试的所有密码的链接的网页来匿名尝试一堆密码,然后让Googlebot进行实际的请求...
RemcoGerlich 2015年

2
“但是正如Esben早在注释中注释的那样,使用GET更改状态违反了这样的Rest服务。”我也注意到了该注释,但是我看不到有人在说这是GET请求。毕竟,您可以将信息嵌入URI并仍然将其发布。但是,它并不是真正的RESTful,因为URI实际上并不是在命名资源。
约书亚·泰勒

嗨,很好的答案,但我不同意“'?'之后没有可变部分” ...有很多存储完整URL的信息!!!
dagnelies,2015年

2
“使用GET更改状态违反了这样的Rest服务” –让我们不要过于关注REST。使用GET更改状态违反了HTTP
丹·埃利斯

69

您所提议的既不是安全的也不是RESTful的。

@Netch已经提到了日志问题,但是还有另一个问题,因为您正在显示通过HTTP发送的密码,因此通过任何类型的网络嗅探器或中间人攻击来捕获密码都是很简单的。

使用REST进行GET请求时,URL中的不同元素表示更细粒度的元素。您的URL读起来就像是返回了OLDPASSWD的NEWPASSWD部分一样,而该部分是resetpassword的一部分。这没有任何语义上的意义。GET不应用于保存数据。

您应该这样做:

POST https://www.example.com/user/joe/resetpassword/
{oldpasswd:[data], newpasswd:[data]}

POST是因为您正在写数据,而https是因为您不希望它被嗅探。

(这实际上是低安全性。您应该做的绝对最低限度。)


2
这不是在客户端哈希密码吗?推荐这个吗?
罗恩·弗里曼

1
注意:这将不允许强制执行密码(长度等)要求。对于您而言,这不是一个问题,尽管这是一种频繁的安全做法,并且某些实体有时需要这样做。
Paul Draper

8
通常,您不是在创建新记录,而是在更新现有记录,因此应该是PUT而不是POST。

4
这不是很好的RESTful。resetpassword不是资源,更不用说子资源了。但是,/user/joe/password是更好但不是最佳的。
whirlwin 2015年

12
@CamilStaps不,您不能使用PUT,因为它PUT是幂等的。但是,当密码已更改从secretsupersecret成功地,那么同样的请求将失败,第二次,所以POST是正确的在这里。当然,正如@whirlwin所说,此资源的名称并不好。
Residuum

60

拟议的方案在几个领域都有问题。

安全

URL路径经常被记录;将未隐藏的密码放在路径中是不明智的做法。

HTTP

身份验证/授权信息应出现在“授权”标头中。对于基于浏览器的内容,可能会包含Cookie标头。

休息

resetpasswordURL中的动词通常是非代表性状态转移范例的明确标志。URL应该代表资源。GET是什么意思resetpassword?还是删除?

API

此方案要求始终知道先前的密码。您可能需要考虑更多情况;例如,密码丢失。


您可以使用基本身份验证或摘要身份验证,这是众所周知的方案。

PUT /user/joe/password HTTP/1.0
Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
Content-Type: text/plain
Host: www.example.com

NEWPASSWD

它不会在路径中放入超敏感信息,并且遵循HTTP和REST约定。

如果您需要允许其他某种授权方式(例如,通过已验证的通道发送的某些令牌来重置密码),则可以简单地使用其他Authorization标头,而无需更改其他任何内容。


4

除了安全性,问题还在于它不是一种非常RESTful的方法。

OLDPASSWD并且NEWPASSWD不代表资源层次结构中的任何内容,更糟糕的是,该操作不是幂等的。

因此,您只能将其POST用作动词,并且不应在资源路径中包含两个密码。


1
通常,您不是在创建新记录,而是在更新现有记录,因此应该是PUT而不是POST。

2
@CamilStaps如果只是设置密码,则可以。但是,由于大概也需要验证旧密码,因此它使操作成为非幂等,因此PUT不符合动词资格。可以重新调整它的工作方式,PUT但以目前的形式却不能。
biziclop,2015年

OLDPASSWD是身份验证信息,完全不应出现在URL中。

不一定,通常的做法是在身份验证之外明确要求使用旧密码。
biziclop 2015年

3

问题是在您的请求中避免使用纯文本密码。有两种选择可以满足宁静的Web服务需求。

1.客户端哈希

  • 我猜您正在存储密码,例如hash(password + salt)
  • 您可以在客户端用盐将新密码散列
  • 这意味着:在客户端创建一个新的盐,创建一个哈希,例如hash(newPassword + newSalt)
  • 将新创建的哈希值和盐发送到您的静态Web服务
  • 将旧密码也发送为hash(oldPassword + oldSalt)

2.加密

  • 为/ otk / john之类的用户创建一个“一次性密钥”(otk)资源
  • 此资源返回一个安全的随机唯一一次密钥,例如kbDlJbmNmQ0Y0SmRHZC9GaWtRMW0ycVJpYzhMcVNZTWlMUXN6ZWxLdTZESFRs和唯一ID,例如95648915125
  • 您的静态网络服务必须存储此随机otk,以便与ID 95648915125进行下一次安全通信。
  • 使用otk加密您的新密码和旧密码,例如AES(出于安全原因,您应将两个单独的otks用于旧密码和新密码)
  • 将加密的密码发送到ID为95648915125的更改密码资源中
  • 一个otk和ID组合只能使用一次,因此在更改密码后必须删除该组合
  • 可能的更好选择:通过Basic-Auth发送当前/旧密码。

注意:这两个选项都需要HTTPS!


1
为什么要对密码交换进行双重加密(使用OTK和HTTPS的加密方案)?什么是HTTPS未涵盖的攻击媒介?
巴特·

1
唯一的目的是避免可能的服务器日志。尽管使用了HTTPS,但也可以记录HTTP请求正文(例如,使用新的明文密码)。其他可能的攻击是使用特别用于内部目的的自签名证书。
maz258 2015年

2

密码重置操作的功能是什么?

  1. 它改变了一些东西。
  2. 有一个它设置为的值。
  3. 仅允许某些人这样做(用户,管理员或其中之一,也许有不同的规则,关于二者的行为方式)。

这里的第1点表示您不能使用GET,您必须将表示密码更改操作的内容发布到表示处理密码更改的资源的URI,或者将表示新密码的内容发布到表示密码或表示内容的URI(例如,用户),该密码就是其中的一项功能。

通常,我们会进行POST,这尤其重要,因为它会很麻烦地放置一些我们以后无法获取的东西,当然我们也无法获取密码。

因此,第2点将是发布后代表新密码的数据。

第三点意味着我们需要授权请求,这意味着如果用户是当前用户,我们将需要向我们证明当前密码(尽管不一定要接收当前密码,例如,基于哈希的挑战用来证明它的知识而不发送它)。

因此,URI应该类似于<http://example.net/changeCurrentUserPassword><http://example.net/users/joe/changePassword>

我们可能决定要在POST数据以及正在使用的一般授权机制中接收当前密码。

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.