使用rand()进行CSRF,它是否安全(r)?

I have this function for CSRF protection, it is pretty insane.

function GenToken($ranLen) {
    $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$()';
    $randomString = '';
    for ($i = 0; $i < $ranLen; $i++) {
        $randomString .= $characters[rand(0, strlen($characters) - 1)];
    }
    return $randomString;
}

It is called up by this:

$token = GenToken(rand(32,128));

It uses PHP's rand() which I know is far from ideal when it comes to creating random numbers.

What I am wondering is just how bad is it? Is this function suitable for 'good' (granted wacky) CSRF protection? It sure as hell generates one heck of a string.

Currently the function is only used for CSRF however it could be used for other short random strings like a code emailed to the user to activate their account ect. Is this acceptable?

It'll probably be good enough, as long as the generated tokens are user-specific and/or are expired relatively soon. However, if you're going to change it at all, you should change it to use a decent PRNG, which is available on most systems in the form of /dev/random and can be accessed using a number of ways:

mcrypt_create_iv($raw_salt_len, MCRYPT_DEV_URANDOM)
openssl_random_pseudo_bytes($raw_salt_len)
fopen('/dev/urandom', 'r')  // then fread enough bytes from it

Simply bin2hex or base64_encode the return values of the above. Your rand (or better mt_rand) solution should only be a fallback in case none of the above are available.

For the similar task I'd prefer to use built-in php function called uniqid http://www.php.net/manual/en/function.uniqid.php It should be faster and safer then your implementation