What is the best way to generate a login token? Is this method of authentication vulnerable to attack?
I have to implement login tokens in my Lithium (the PHP framework) based application. Two reasons:
I want to have a "remember me" function.
I also need a way of tracking logins on the server so that I can verify authenticated users on a node.js socket server like so:
- User requests a page
- Server returns a view with a session token somewhere in the HTML
- The client side JS reads the token and send it to the node.js server in an attempt to establish a connection via web sockets.
- The server receives the connect request and verifies the token sent to it with the PHP server.
- Allows or denies a connection based on the result.
So this is a two part question, and it's just to verify that I'm not being an idiot because the security on this site is of higher priority than usual.
Is this a reasonable way of creating a login token?
<?php
// String::hash() generates a sha512 (by default) hash.
String::hash(time() . $user['username']);
?>
Is the web socket authentication system I proposed sane? Can you see any problems arisi开发者_如何学JAVAng or any more efficient ways of doing it?
First, you should change the way your login token is generated. A hash of the current time concatenated with the username is far from being difficult to guess; which is a necessary condition for it to be secure. There are many ways to do this, what's crucial is that you use a good source of randomness. You could do:
list(,$token) = unpack('H*', openssl_random_pseudo_bytes(15, $safe));
$safe or die("unsafe source");
The overall method you're using is only secure if you the bearer token you're passing around is never sent unencrypted. This means every time it is transmitted it must be transmitted over SSL/TLS.
There's still the problem that you may accidentally send the token to the wrong place, so you must be extra careful if any destination is somehow dynamically generated (e.g. through some discovery protocol). The only way to avoid this problem would be to use cryptography.
You should look at the RequestToken
class in Lithium: http://li3.me/docs/lithium/security/validation/RequestToken::check()#source
It handles CSRF protection, and uses cryptographically secure random tokens, based on principles similar to the above, but with an extra layer of protection with bcrypt, which can match any number of unique hashes.
You could use the uniqid() function to generate a unique ID, to increase your security, and then you can drop or use together with the time.
<?php
String::hash(time() . uniqid() . $user['username']);
?>
精彩评论