问题
I have a registration page that receives tokens ad parse them and login the user if the parameters apply.
Between the time that i checked the token, to the time that i removed the token from the db, another user can use the same token to login. is there a way to make sure that specific range of lines of code will be executed with not interference, so i won't have race condition problem ?
thanks
update
I have two servers.
- apache tomcat 6
- red5 v0.9 (free java based flash media streaming and communication server)
I'm writing a game application for Facebook.
the game itself is written in adobe flash builder 2.
the game itself will be served using the red5 server. the problem is that red5 does not receive the request and response headers and because of that cannot retrieve session information to use in order to fetch information from facebook.
to resolve the issue the user connect to the tomcat server, that page checks the session for facebook related information and uses tinyFBClient to connect to facebook, and to store the information in the mysql db (user details), in order to make sure that this same user is the user that's going to connect to red5.
once a token is created. the tomcat page displays an object HTML element in order to show the relevant SWF file (game file). the tomcat page passes the token to that SWF file. once the SWF file is loaded, it takes that token and uses it to connect to red5 and for it to find out the user information.
I hope that description helps you understand my needs. thanks for all of your support!
回答1:
You could use a Lock object.
Using Lock objects has advantages over the more primitive synchronized blocks and methods.
回答2:
You could synchronize the block of code, such that only one thread at a time could execute it. However, this doesn't seem like a very good solution, as it will slow down your application. You would like to have multiple users logging in concurrently.
How are tokens created? If you were to generate them on the server side in response to a user logging in, then one user shouldn't be able to use another user's token.
回答3:
Sounds like you need a synchronized method / block:
See here for example (synchronized method)
http://java.sun.com/docs/books/tutorial/essential/concurrency/syncmeth.html
Be careful not to over-cook it the otherway ! Too much synchronization can lead to bottlenecking !
回答4:
I'm not sure why you're creating a token for a login. Your question seems to imply this token is on the database and not in memory. If so, synchronization and mutexes won't really help, what you need is to lock the database record with a "select for update".
Maybe this gets into a lot of irrelevant complexity, but why are you creating a token to do a login? Any time I do a login, I simply collect the userid and password from the screen or incoming form, check against the database to see if the combination is valid, and if so let the user in. What do you need a token for?
回答5:
You say that you "remove the token from the db". Is the database a SQL database? If so then you can use a transaction to avoid the race condition. It would look something like this:
- Create a unique session ID, e.g.
UUID sessionID = UUID.randomUUID();
- Begin transaction
- Delete any tokens from the DB that match the one in the request, e.g.
DELETE FROM Tokens WHERE TokenID = <requested-token> - Get the affected row count
- If the affected row count is exactly 1, then the token was valid. Create a session, e.g.
INSERT INTO Session VALUES (sessionUUID, userID, loginTime, ...) - Commit transaction
Now if the login was successful (i.e. the affected row count was exactly 1), send the client a cookie containing the session ID.
来源:https://stackoverflow.com/questions/2222175/java-race-conditions-is-there-a-way-to-make-sure-several-lines-of-code-will-b