REST风格的密码重置
构build重置密码的RESTful资源的正确方法是什么?
这个资源是为那些遗失或忘记密码的人设置的密码重置器。 它使他们的旧密码无效,并通过电子邮件向他们发送密码。
我有两个select是:
POST /reset_password/{user_name}
要么…
POST /reset_password -Username passed through request body
我很确定这个请求应该是POST。 我不太确定我select了一个合适的名字。 而且我不确定是否应该通过URL或请求主体传递user_name。
更新:(进一步评论如下)
我会去这样的事情:
POST /users/:user_id/reset_password
您有一组用户,其中单个用户由{user_name}
指定。 然后,您将指定操作的操作,在这种情况下是reset_password
。 这就像是说“为{user_name}
创build( POST
)新的reset_password
操作”。
先前的回答:
我会去这样的事情:
PUT /users/:user_id/attributes/password -- The "current password" and the "new password" passed through the body
您将拥有两个集合,一个用户集合以及每个用户的属性集合。 用户由:user_id
指定,属性由password
指定。 PUT
操作更新收集的已解决的成员。
未经身份validation的用户
我们在api/v1/account/password
端点上执行一个PUT
请求,并需要一个带有相应帐户邮件的参数来标识用户想要重置(更新)密码的帐户:
PUT : /api/v1/account/password?email={email@example.com}
注意: 正如@DougDomeny在他的评论中提到的,在URL中传递电子邮件作为查询string是一个安全风险。 使用https
时,GET参数不会暴露(而且您应该始终使用适当的https
连接来处理此类请求),但是还存在其他安全风险。 你可以在这篇博文中阅读更多关于这个主题的文章 。
传递电子邮件在身体将是一个更安全的替代传递它作为一个GET参数:
PUT : /api/v1/account/password data : { "email": "email@example.com" }
答案有一个202
接受的答复意思是:
该请求已被接受处理,但处理尚未完成。 该请求可能最终也可能不会最终被执行,因为在处理实际发生时它可能被禁止。 没有这样的asynchronous操作重新发送状态码的function。
用户将通过email@example.com
收到一封电子邮件,处理更新请求取决于电子邮件中链接的操作。 该电子邮件包含指向重置密码表单的链接,其中包含重置密码标记作为查询string。
当表单提交一个新的密码和令牌作为input时,重置密码过程将发生。 表单数据将再次与PUT
请求一起发送,但这次包括令牌,我们将用新的值replace资源密码:
PUT : /api/v1/account/password? data : { "token":"1234567890", "new":"password" }
回应将是一个204
没有内容的回应
服务器已经完成了请求,但不需要返回实体主体,并且可能想要返回更新后的元信息。 响应可以包含新的或更新的实体头信息,如果存在的话应该与请求的变体相关联。
经过身份validation的用户
对于想要更改密码的authentication用户,可以在没有电子邮件(服务器知道我们更新密码的帐户)的情况下立即执行PUT
请求。 在这种情况下,表格将提交两个字段:
PUT : /api/v1/account/password? data : { "old":"password", "new":"password" }
让我们一秒钟就能看到RESTful。 为什么不使用密码的DELETE操作来触发重置? 有道理,不是吗? 毕竟,你有效地丢弃了现有的密码而转而使用另一个密码。
这意味着你会这样做:
DELETE /users/{user_name}/password
现在,两个重要的警告:
-
HTTP DELETE被认为是幂等的 (如果你多次使用它,那么就说“没什么大不了的”)。 如果你正在做标准的东西,比如发送“密码重置”电子邮件,那么你将遇到问题。 您可以使用布尔型“Is Reset”标志来解决此用户/密码的标记问题。 在每次删除时,你检查这个标志; 如果没有设置, 那么你可以重置密码并发送你的电子邮件。 (请注意,拥有此标志也可能有其他用途。)
-
您不能通过表单使用HTTP DELETE ,因此您必须通过POST进行AJAX调用和/或通过DELETE隧道。
您通常不希望在初始请求中删除或销毁用户的现有密码,因为这可能是由无权访问电子邮件的用户(无意或故意)触发的。 而应更新用户logging上的重置密码令牌,并将其发送到电子邮件中包含的链接中。 点击链接将确认用户收到令牌,并希望更新他们的密码。 理想情况下,这也是时间敏感的。
在这种情况下,RESTful操作将是POST:触发PasswordResets控制器上的创build操作。 行动本身会更新令牌并发送电子邮件。
实际上,我正在寻找答案,而不是提供一个答案 – 但在REST上下文中,“reset_password”听起来不对,因为它是一个动词,而不是一个名词。 即使你说你正在做一个“重置行动”的名词 – 使用这个理由,所有的动词都是名词。
另外,也许没有人想要find相同的答案,你可以通过安全上下文获得用户名,而不必通过url或身体发送,这让我感到紧张。
如果您决定使用/ users / {id} / password方法,则不会有更改密码并发送新密码的内容,并坚持您的意见,即请求是自己的资源。 即/ user-password-request /是资源,正在使用PUT,用户信息应该在正文中。 我不会更改密码,Id发送一个电子邮件给用户,其中包含一个链接到一个页面,其中包含一个request_guid,可以传递一个POST / user / {id} / password /?request_guid = XXXXX
这将改变密码,并且不允许有人通过请求改变密码来给用户提供软pipe。
另外,如果有未完成的请求,初始PUT可能会失败。