问题
I've implemented the Improved Persistent Login Cookie Best Practice for a "remember me" option.
This works fine when requests are in sequence (traditional page loading). In this case you are sure that the next request will have the same series identifier and the token that was last sent by the server.
But in the case of AJAX requests, where multiple requests are coming in parallel from the same browser, the first request will result in the generation of a new token number. But the other requests will not have this newly generated token number and they'll we denied access considering it as a theft.
How do we get around this problem?
回答1:
Based on the proposed solution on the aforementioned Drupal thread (https://www.drupal.org/node/327263#comment-3428038), I'm wondering if we cannot have a simpler algorithm.
Instead of storing "old" replaced tokens in a short lived caching table, why not use the current users session?
1. User logs in with PL cookie
If series & token are in PL table:
2. User session is populated with the last valid token
3. new token is given to client
4. user is logged in
If series key is in PL table, but token is not:
2. check if current user session still holds the latest replaced token
If found:
3. user is logged in. No new token is provided since one was generated in the first request.
If not found:
3. Assume keys are stolen - series is destroyed
This algorithm won't work in load balanced scenarios though, when the session state is not properly replicated to all nodes though!
回答2:
I think you confused remember me with CSRF (Cross Site Request Forgery) protection tokens. CSRF tokens protect application by disabling a possibility of unauthenticated "functionality execution". And they do that by issuing nondeducible token to each response, and verifying it upon reciving a request.
Remember me feature is a feature which allows user to login, even if the original session was long gone. Without the need of providing his username/password again. You should set your remember me token, once or once on every successful login. Not in every response. You do not set session cookie in every response why would you set a remeber me token ?
回答3:
I've been reading a bit about this since I have the same issue.
Barry Jaspan and Charles Miller's technique seems to be unusable (especially in AJAX setups) due to the fact that between generating a new token on the server and applying that in a cookie, as you point out, a lot can happen.
In our case it is the asynchronous nature, but there might be other cases where the value does just not end up in the cookie as it is stored on the server (e.g. navigating away from the page before it loaded).
Barry seems to acknowledge this.
Secondly, invalidating tokens (e.g. on password change) makes you end up with a lot of "ghost" cookies. Each access with one of them invalidates all other sessions (which are at that point likely to have valid ones among them).
Because of these limitations, I think the best solution is a combination of:
- HTTPS (SSL) use
- this technique, but without re-generation on every request
- tracking invalidation by user (to handle second remark above)
- HTTP-only cookies (to avoid script access to them)
I have sent a message to Barry to consider a notice about this on his page.
来源:https://stackoverflow.com/questions/13613526/how-to-combine-a-persistent-login-cookie-with-parallel-ajax-requests