在CGI中實現session的想法和實現 (轉)

worldblog發表於2007-12-10
在CGI中實現session的想法和實現 (轉)[@more@]


  對於客戶端的每一次登陸,在生成一個session,作為一個在伺服器上,例如在“/tmp”下。
檔案命名為sess_開頭,在加上一個隨機的字串,這個字串稱之為session_id。
  在檔案中儲存的內容包括:
  1、的最後一次活動時間。(用來檢查使用者是否長時間沒有操作,視為已經退出登陸)。
  2、一個隨機的字串。(用來驗證客戶端的身份,這個字串同時作為cookie發往客戶端)。
  3、客戶端的IP.
  4、實際要儲存的資料。例如使用者的ID,密碼等。

  在使用者登陸時,生成這個檔案,並且,將那個隨機字串發到客戶端的cookie. 
  在以後的每個頁面的超連線,或是FORM中的要跟入session_id.
  每個頁面開始,要:
  1、檢查是否超時。
  2、對比cookie中的字串和session檔案中的,驗證客戶身份。
  3、對比客戶端IP和session檔案中的IP,驗證客戶身份。
  4、讀出資料,供下面使用

  5、重新整理最後活動時間
  6、生成新的隨機字串,重新整理session中對應部分,並將其作為cookie發往客戶端。


  因為我正在做的專案要求比較高的性,所以我在這方面考慮的比較多些,但我知道這樣肯定還
不是完全安全的。如果誰發現了什麼,麻煩告訴我。

  下面是我的部分實現程式碼:
 
  set_session()在登陸是。
  start_session()在每個頁面的前面呼叫。
  kill_session()在退出登陸是呼叫。
  clean_session() 用來刪除過期的session檔案。

#include
#include
#include
#include
#include
#include
#include
#include

#define REMOTE_ADDR1 getenv("REMOTE_ADDR")
#define HTTP_COOKgetenv("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 *;
  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 ran 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] = '';
 
/**
  * 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] = '';
/**
  * 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=%sn",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;


  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  {
  if( buffer[i] == 'n'  )
  {
  temp[j] = '';
  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 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,"%10dn",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] = '';
 

/**
  * 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/htmlnn");
  printf("

";
  print_title("請重新登陸!");
  printf("n");

  printf("

n");
  printf("對不起,請重新登陸。

n");
  printf("你長時間沒有操作,登陸已經超時。或者是發生了錯誤。

n");
  printf("如果是後者,請與管理人員聯絡。n");
  printf("<!--%s--&gt",n);
  printf("");
  printf("n");
}

 


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-990868/,如需轉載,請註明出處,否則將追究法律責任。

相關文章