1

I am creating a RESTful web service and I try to follow the conventions and recomendations for creating a good web service. Now I have come to a halt though. I have a User entity in my system that I have regular CRUD paths for. I want to expose an API to deal with forgotten passwords. It will take a username in the request and then check if it finds the user. If it does it will change the password and change the password to the autogenerated one and send an email to the user.

I read this: RESTful actions/services that don't correspond to an entity? and I see that I maybe should start looking at non database entities as resources also.

But I still have issues with finding a concept for forgotten passwords in my API.

What could I name the path and what HTTP method is appropriate for it? Should PUT be used since it will update the user with a new password?

4

2 回答 2

5

I want to expose an API to deal with forgotten passwords. It will take a username in the request and then check if it finds the user. If it does it will change the password and change the password to the autogenerated one and send an email to the user.

If you really want to be RESTful:

What could I name the path and what HTTP method is appropriate for it?

It is not a PUT nor a GET, since they are idempotent methods (meaning you executing them once or 10 times should give the exact same outcome) and what you want is not: if requested 10 times, 10 different passwords will be generated.

There are other reasons, but the above is simple and leave no doubts. So a POST it is.

About the URL, since password can be considered a subresource (a part of) of user, considering the URL for the user resource http://www.example.com/rest/user, it makes sense to design the password URL as:

http://www.example.com/rest/user/password

This way, if someone wants to set the password, he should send a PUT to that URL with the new password (idempotent behavior!).

Now the a password reset action, I'd make it a POST to that URL, possibly with some more specific content like password-reset and some necessary keywords (the answer for a secret question, maybe) in the POST body. If that content does not come, a 400 Bad Request response would be appropriate. If the requester tries too much, a 403 Forbidden should be issued during the "retry-wait-period". Needless to say, both the PUT and the POST should take place within a secure, encrypted (HTTPS, anyone?), channel.

于 2013-05-19T18:46:30.240 回答
1

I think that your approach has obvious weakness. Think that you expose URL that generates new password for user, for example: POST to URL http://mycompany.com/app/user/foobar/resetpassword

Obviously this URL cannot be password protected: otherwise use that forgot his password cannot reset it. OK, this means that everyone that knows the user name can reset password of the user. Even every 5 seconds. Or milliseconds... Cool!

This means that you have to somehow protect your system from such "naive" hacker's attack.

I recently implemented similar system and can suggest you my solution.

  1. Expose open URL that allows to start the process, e.g. http://mycompany.com/app/user/foobar/resetpassword. This URL does not change the password. It just creates email that contains yet another clickable URL like http://mycompany.com/app/user/resetpassword/UNIQUETOKEN. The token is something that you cannot guess.
  2. User receives the email and clicks the link. This time the password is changed and appropriate email is sent to the same email.

This mechanism protects your system from naive hacker's attack and from occasionally pressed "reset password" button because the first action does not actually change password. Only user that can access his email can indeed change password.

Concerning the token generation. The best solution is to store mapping of token to password change request in DB, so you can limit click attempts and make request expiration timeout. I implemented simpler solution for some reasons: the token actually contains encrypted user name and date when password was requested, so I implemented the request expiration but cannot limit number of clicks on the token contained URL. However the implementation is very simple and stateless.

于 2013-05-19T18:25:19.020 回答