我正在创建一个RESTful Web服务,我尝试遵循约定和推荐来创建一个好的Web服务。现在我已经停止了。我的系统中有一个用户实体,我有常规的CRUD路径。我想公开一个API来处理忘记的密码。它将在请求中使用用户名,然后检查它是否找到用户。如果是,它将更改密码并将密码更改为自动生成的密码并向用户发送电子邮件。
我读到这个:RESTful actions/services that don't correspond to an entity?我看到我也许应该开始将非数据库实体视为资源。
但我仍然遇到在我的API中找到忘记密码概念的问题。
我可以为路径命名什么,以及适合的HTTP方法是什么?是否应该使用PUT,因为它会用新密码更新用户?
答案 0 :(得分:5)
我想公开一个API来处理忘记的密码。它将在请求中使用用户名,然后检查它是否找到用户。如果是,它将更改密码并将密码更改为自动生成的密码并向用户发送电子邮件。
如果你真的想成为RESTful:
我可以命名路径以及适用于它的HTTP方法是什么?
它不是PUT
也不是GET
,因为它们是幂等方法(意味着你执行一次或10次应该给出完全相同的结果)并且你想要的不是:如果要求的话10次,将生成10个不同的密码。
还有其他原因,但上述内容很简单,不容置疑。所以它是POST
。
关于网址,因为password
可以被视为user
的子资源(一部分),考虑user
资源的网址{{ 1}},将密码URL设计为:
http://www.example.com/rest/user
这样,如果有人想设置密码,他应该使用新密码向该URL发送http://www.example.com/rest/user/password
(幂等行为!)。
现在密码重置操作,我会将其设为PUT
到该网址,可能还有一些更具体的内容,例如POST
和一些必要的关键字(在password-reset
机构回答一个秘密问题。如果未提供该内容,则POST
响应将是合适的。如果请求者尝试过多,则应在“重试等待期”期间发出400 Bad Request
。毋庸置疑,403 Forbidden
和PUT
都应该在安全,加密(HTTPS,任何人?)渠道中进行。
答案 1 :(得分:1)
我认为你的方法有明显的弱点。认为您公开了为用户生成新密码的URL,例如:POST
到网址http://mycompany.com/app/user/foobar/resetpassword
显然这个URL不能被密码保护:否则使用那个忘记密码就无法重置它。好的,这意味着知道用户名的每个人都可以重置用户的密码。甚至每5秒钟一次。或者毫秒......很酷!
这意味着您必须以某种方式保护您的系统免受这种“天真”的黑客攻击。
我最近实施了类似的系统,可以向您推荐我的解决方案。
http://mycompany.com/app/user/foobar/resetpassword
。此URL不会更改密码。它只是创建包含另一个可点击的网址的电子邮件,例如http://mycompany.com/app/user/resetpassword/UNIQUETOKEN
。令牌是你无法猜测的。 这种机制可以保护您的系统免受天真的黑客攻击,并偶尔按下“重置密码”按钮,因为第一个操作实际上并没有更改密码。只有能够访问其电子邮件的用户才能更改密码。
关于令牌生成。最佳解决方案是在DB中存储令牌到密码更改请求的映射,这样您就可以限制点击尝试并使请求到期超时。我出于某些原因实现了更简单的解决方案:令牌实际上包含加密的用户名和请求密码的日期,因此我实现了请求到期但不能限制包含令牌的URL的点击次数。 然而,实现非常简单且无状态。