在CGI中完成session的想法與完成
發(fā)表時(shí)間:2024-06-09 來(lái)源:明輝站整理相關(guān)軟件相關(guān)文章人氣:
[摘要]對(duì)于客戶(hù)端的每一次登陸,在服務(wù)器生成一個(gè)session,作為一個(gè)文件存儲(chǔ)在服務(wù)器上,例如在“/tmp”下。 文件命名為sess_開(kāi)頭,在加上一個(gè)隨機(jī)的字符串,這個(gè)字符串稱(chēng)之為session_id。 在文件中存儲(chǔ)的內(nèi)容包括: 1、用戶(hù)的最后一次活動(dòng)時(shí)間。(用來(lái)檢查用戶(hù)是否長(zhǎng)時(shí)間沒(méi)有操作,...
對(duì)于客戶(hù)端的每一次登陸,在服務(wù)器生成一個(gè)session,作為一個(gè)文件存儲(chǔ)在服務(wù)器上,例如在“/tmp”下。
文件命名為sess_開(kāi)頭,在加上一個(gè)隨機(jī)的字符串,這個(gè)字符串稱(chēng)之為session_id。
在文件中存儲(chǔ)的內(nèi)容包括:
1、用戶(hù)的最后一次活動(dòng)時(shí)間。(用來(lái)檢查用戶(hù)是否長(zhǎng)時(shí)間沒(méi)有操作,視為已經(jīng)退出登陸)。
2、一個(gè)隨機(jī)的字符串。(用來(lái)驗(yàn)證客戶(hù)端的身份,這個(gè)字符串同時(shí)作為cookie發(fā)往客戶(hù)端)。
3、客戶(hù)端的IP.
4、實(shí)際要存儲(chǔ)的數(shù)據(jù)。例如用戶(hù)的ID,密碼等。
在用戶(hù)登陸時(shí),生成這個(gè)文件,并且,將那個(gè)隨機(jī)字符串發(fā)到客戶(hù)端的cookie.
在以后的每個(gè)頁(yè)面的超連接,或是FORM中的要跟入session_id.
每個(gè)頁(yè)面開(kāi)始,要:
1、檢查是否超時(shí)。
2、對(duì)比cookie中的字符串和session文件中的,驗(yàn)證客戶(hù)身份。
3、對(duì)比客戶(hù)端IP和session文件中的IP,驗(yàn)證客戶(hù)身份。
4、讀出數(shù)據(jù),供下面程序使用
5、刷新最后活動(dòng)時(shí)間
6、生成新的隨機(jī)字符串,刷新session中對(duì)應(yīng)部分,并將其作為cookie發(fā)往客戶(hù)端。
因?yàn)槲艺谧龅捻?xiàng)目要求比較高的安全性,所以我在這方面考慮的比較多些,但我知道這樣肯定還
不是完全安全的。如果誰(shuí)發(fā)現(xiàn)了什么漏洞,麻煩告訴我。
下面是我的部分實(shí)現(xiàn)代碼:
set_session()在登陸是調(diào)用。
start_session()在每個(gè)頁(yè)面的前面調(diào)用。
kill_session()在退出登陸是調(diào)用。
clean_session() 用來(lái)刪除過(guò)期的session文件。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <dirent.h>
#define REMOTE_ADDR1 getenv("REMOTE_ADDR")
#define HTTP_COOKIE getenv("HTTP_COOKIE")
char *sess_user_name;
char *sess_user_pwd;
static void print_session_error(char *);
static void clean_session_file();
char *set_session(char *name,char *pwd)
{
char str_now[11];
char hash_key[17];
char *session_id;
time_t now;
FILE *sf;
char sfp[32];
int i,temp,r;
time(&now);
/**
* clean time out session file
*/
clean_session_file();
/**
* get str_now
*/
sprintf(str_now,"%10d",now);
/**
* get random hash_key
*/
srand(now);
r = rand();
for(i=0;i<16;i++)
{
srand(r);
r = rand();
hash_key[i] = r%26 + ’a’;
}
hash_key[16] = ’\0’;
/**
* get more random session_id;
*/
temp = rand();
srand(temp);
r = rand();
session_id = (char*) malloc(17*sizeof(char));
for(i=0;i<16; i++)
{
srand(r);
r = rand();
session_id[i] = r%26 + ’A’;
}
session_id[16] = ’\0’;
/**
* create session file
*/
strcpy(sfp,"/tmp");
strcat(sfp,"/sess_");
strcat(sfp,session_id);
sf = fopen(sfp,"w");
chmod(sfp,06777);
if( sf == NULL )
{
tc_error_page("can’t creat session file");
}
/**
* fputs session file
*/
fputs(str_now,sf);
fputs("\n",sf);
fputs(hash_key,sf);
fputs("\n",sf);
fputs(REMOTE_ADDR1,sf);
fputs("\n",sf);
fputs(name,sf); //sess_user_name
fputs("\n",sf);
fputs(pwd,sf); // sess_user_pwd_
fputs("\n",sf);
fclose(sf);
/**
* set cookie
*/
printf("Set-Cookie:hash_key=%s\n",hash_key);
return session_id;
}
void start_session()
{
int i,j,k;
char *session_id;
FILE *sf;
char sfp[32];
time_t now;
int r;
char buffer[256];
char temp[64];
char str_time[16];
char str_hash_key[20];
char str_client_ip[20];
char *str_array[6];
sess_user_name = (char*)malloc(32*sizeof(char));
sess_user_pwd = (char*)malloc(32*sizeof(char));
str_array[0] = str_time;
str_array[1] = str_hash_key;
str_array[2] = str_client_ip;
str_array[3] = sess_user_name;
str_array[4] = sess_user_pwd;
[page_break] session_id = cgi_val(entries,"session_id");
/**
* open session file
*/
strcpy(sfp,"/tmp");
strcat(sfp,"/sess_");
strcat(sfp,session_id);
sf = fopen(sfp,"rb+");
if( sf == NULL )
/** can’t open session file,maybe session has time out **/
{
print_session_error("1");
exit(1);
}
/**
* read session var
*/
bzero(buffer,256);
fread(buffer,1,256,sf);
for(i=0,j=0,k=0;k<5 && i<strlen(buffer);i++)
{
if( buffer[i] == ’\n’ )
{
temp[j] = ’\0’;
strcpy(str_array[k],temp);
j = 0;
k ++;
}
else
{
temp[j++] = buffer[i];
}
}
/**
* check active time
*/
time(&now);
if( now - atoi(str_time) > atoi(parse_config_file("session_live_time")) )
{
print_session_error("2");
exit(1);
}
/**
* compare client hash_key to session hash_key
*/
if( HTTP_COOKIE == "" strcmp( HTTP_COOKIE+9 , str_hash_key ) != 0 )
{
print_session_error("3");
exit(1);
}
/**
* compare client ip to session ip
*/
if( strcmp( REMOTE_ADDR, str_client_ip ) != 0 )
{
print_session_error("4");
exit(1);
}
/**
* refresh session active time
*/
time(&now);
sprintf(str_time,"%10d\n",now);
fseek(sf,0,SEEK_SET);
fputs(str_time,sf);
/**
* get new hash_key
*/
srand(now);
r = rand();
for(i=0;i<16;i++)
{
srand(r);
r = rand();
str_hash_key[i] = r % 26 + ’a’;
}
str_hash_key[16] = ’\n’;
str_hash_key[17] = ’\0’;
/**
* refresh session hash_key
*/
fseek(sf,11,SEEK_SET);
fputs(str_hash_key,sf);
fclose(sf);
/**
* send cookie refresh client hash_key
*/
printf("Set-Cookie:hash_key=%s",str_hash_key);
}
void kill_session()
{
char *session_id;
char *session_path;
char sfp[128];
session_id = cgi_val(entries,"session_id");
strcpy(sfp,"/tmp");
strcat(sfp,"/sess_");
strcat(sfp,session_id);
remove(sfp);
}
void clean_session_file()
{
DIR *pdir;
struct dirent *ent;
char *path;
char *filename;
char filepath[64];
int fd;
char str_time[11];
time_t now;
path = "/tmp";
pdir = opendir(path);
if(pdir != NULL)
{
while( ent =readdir(pdir) )
{
filename = ent->d_name;
if( strncmp(filename,"sess_",5)==0 )
{
strcpy(filepath,path);
strcat(filepath,"/");
strcat(filepath,filename);
fd = open(filepath,O_RDONLY);
read(fd,str_time,10);
time(&now);
if( now - atoi(str_time) > atoi(parse_config_file("session_live_time")) )
{
remove(filepath);
}
close(fd);
}
}
}
closedir(pdir);
}
void print_session_error(char *n)
{
printf("Content-type:text/html\n\n");
printf("<html><head>";
print_title("請(qǐng)重新登陸!");
printf("</head>\n");
printf("<body>\n");
printf("對(duì)不起,請(qǐng)重新登陸。<p>\n");
printf("你長(zhǎng)時(shí)間沒(méi)有操作,登陸已經(jīng)超時(shí)。或者是系統(tǒng)發(fā)生了錯(cuò)誤。<p>\n");
printf("如果是后者,請(qǐng)與管理人員聯(lián)系。\n");
printf("<!--%s-->",n);
printf("</body>");
printf("</html>\n");
}