As a web programmer, we are certainly not unfamiliar with the session, session ID is our respective on the server, a unique flag, this ID string can be generated automatically by PHP, or we can give. You may be like me, very concerned about the automatic generation of PHP ID string is how, the probability of conflict, and can not easily be calculated by others, so the following.
We download a copy of the php5.3.6 source code, enter the/ext/session directory, generate session ID function is located in the Session.c file 345 lines, the following details about this function. For the sake of understanding, I adjusted the order of some code.
Phpapi Char *php_session_create_id (Ps_create_sid_args)//* {{{{*/{//these rows define the data required for the hash function, directly over the ~php_md5_ctx Md5_context; Php_sha1_ctx sha1_context; #if defined (have_hash_ext) &&!defined (compile_dl_hash) void *hash_context;# endifunsigned Char *digest;int digest_len;int j;char *buf, *outid;zval **array;zval **token;//used to record $_server[' REMOTE_ The value of ADDR '] char *remote_addr = null;//a timeval structure used to record the current timestamp and the number of milliseconds struct Timeval tv;gettimeofday (&TV, NULL);//if possible, REMOTE_ADDR is assigned a value, in PHP pseudo-code is://if (isset ($_server[' remote_addr '))//{remote_addr = $_server[' remote_addr '];} Note: In CLI mode there is no ~if (Zend_hash_find (&eg (symbol_table), "_server", sizeof ("_server"), (void *) &array) = = SUCCESS && z_type_pp (array) = = Is_array && zend_hash_find ( Z_ARRVAL_PP (Array), "REMOTE_ADDR", sizeof ("REMOTE_ADDR"), (void * *) &token) = = Succes S) {remote_addr = z_strval_pp (token);} /* Maximum 15+19+19+10 bytes *Generate the required session ID, and, of course, subsequent processing ~//format is:%.15s%ld%ld%0.8f, the meaning of each paragraph is as follows://%.15s REMOTE_ADDR? REMOTE_ADDR: "" This line is easy to understand//%ld tv.tv_sec current timestamp//%ld (long int) tv.tv_usec current number of milliseconds//%0.8f PHP_COMBINED_LC G (Tsrmls_c) * 101 Random numbers spprintf (&buf, 0, "%.15s%ld%ld%0.8f", remote_addr? REMOTE_ADDR: "", tv.tv _sec, (long int) tv.tv_usec, PHP_COMBINED_LCG (tsrmls_c) * 10);//below the value of the BUF string to hash//Detect hash function in session configuration/*300 line: enum {ps_hash_func_md5, PS_HASH_FUNC_SHA1, Ps_hash_func_other};812 line: php_ini_entry ("se Ssion.hash_function "," 0 ", Php_ini_all,onupdatehashfunc) 738 lines: Static PHP_INI_MH (Onupdatehashfunc) {... val = Strtol (New_value, &endptr, 10); if (endptr && (*endptr = = ')}) {/* Numeric value */PS (Hash_func) = val? 1:0; return SUCCESS; } ...... ...... The default value of PS (Hash_func) is 0, which is ps_hash_func_md5. */switch (PS (Hash_func)) {///if MD5, hash our BUF string with the MD5 algorithmProcessing. Case Ps_hash_func_md5:php_md5init (&md5_context); Php_md5update (&md5_context, (unsigned char *) buf, strlen (BUF)); Digest_len = 16; Break If it is SHA1, the SHA1 algorithm is used to hash our buf string. Case Ps_hash_func_sha1:php_sha1init (&sha1_context); Php_sha1update (&sha1_context, (unsigned char *) buf, strlen (BUF)); Digest_len = 20; Break, #if defined (have_hash_ext) &&!defined (Compile_dl_hash) Case Ps_hash_func_other:if (!ps (hash_op s) {php_error_docref (NULL tsrmls_cc, E_error, "Inva Lid session hash function "); Efree (BUF); return NULL; } Hash_context = Emalloc (PS (hash_ops)->context_size); PS (Hash_ops)->hash_init (Hash_context); PS (Hash_ops)->hash_update (Hash_context, (unsigned char *) buf, strlen (BUF)); Digest_len = PS (hash_ops)->digest_sizE Break, #endif/* have_hash_ext *//If there is no hash function, then an error, or e_error level, awkward ~ default:php_error_docref (NULL tsrmls_cc, E_error, "Invalid session hash function"); Efree (BUF); return NULL;} Release buf~//embarrassing, that content, content has gone to our hash_context, such as Md5_context, Sha1_context ... Efree (BUF);/*session.entropy_file gives a path to an external resource (file) that will be used as an additional entropy resource in the session ID creation process. For example, in many Unix systems you can use/dev/random or/dev/urandom. SESSION.ENTROPY_LENGTH Specifies the number of bytes read from the above file. The default is 0 (disabled). If entropy_length this configuration is greater than 0, then: */if (PS (entropy_length) > 0) {#ifdef php_win32 unsigned char rbuf[2048]; size_t toread = PS (entropy_length); if (Php_win32_get_random_bytes (Rbuf, (size_t) toread) = = SUCCESS) {switch (PS (hash_func)) { Case Ps_hash_func_md5:php_md5update (&md5_context, Rbuf, toread); Break Case Ps_hash_func_sha1:php_sha1update (&sha1_context, Rbuf, toread); break;# if defined (have_hash_ext) &Amp;&!defined (Compile_dl_hash) Case Ps_hash_func_other:ps (hash_ops)->hash_update (hash_ Context, RBUF, toread); break;# endif/* Have_hash_ext *}} #else int fd; FD = Vcwd_open (PS (entropy_file), o_rdonly); if (FD >= 0) {unsigned char rbuf[2048]; int n; int to_read = PS (entropy_length); while (To_read > 0) {n = read (FD, RBUF, MIN (to_read, sizeof (RBUF))); if (n hash_update (Hash_context, RBUF, N); break; #endif/* Have_hash_ext */} To_read-= n; } close (FD); }//the logical #endif}//at the end of Entropy_length>0 is still part of the hash calculation, it seems our hash_final (Digest, Hash_context); Efree (Hash_context); break; #endif/* Have_hash_ext */}/*session.hash_bits_per_character allows the user to define how many bits per character will be stored when converting binary hash data into a readable format. The possible values are ' 4 ' (0-9,a-f), ' 5 ' (0-9,a-v), and ' 6 ' (0-9,a-z,a-z, "-", ","). */if (PS (Hash_bits_per_character) < 4|| PS (Hash_bits_per_character) > 6) {PS (hash_bits_per_character) = 4; Php_error_docref (NULL tsrmls_cc, e_warning, "The INI setting Hash_bits_per_character is out of RA Nge (should is 4, 5, or 6)-using 4 for Now ");} Our hashed binary data digest is represented in a readable form by a string and placed in the Outid string outid = Emalloc ((size_t) ((Digest_len + 2) * (8.0f/ps (hash_bits_per_ character))), j = (int) (Bin_to_readable ((char *) digest, Digest_len, Outid, (char) PS (hash_bits_per_character))-O Utid); Efree (Digest); if (Newlen) {*newlen = j;} return to Outidreturn Outid;}