动网论坛,站长建站首选,国内使用量最多的论坛软件 动网论坛官方技术讨论区 站长工具 申请属于您自己的免费论坛
首页 | 新闻资讯 | 网站运营 | 网络编程 | 数据库 | 服务器 | 网页设计 | 图像媒体 | 网络应用 | 搜索优化 | 资源下载 | 动网主机 | DVBOX
    本站内  互联网 ASP论坛  ASP.Net论坛  PHP论坛
  
   Cgi/Perl → 阅读文章

 在CGI中实现session的想法和实现

作者来源: 
阅读 1267 人次 , 2006-3-29 4:05:00 


对于客户端的每一次登陆,在服务器生成一个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 <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;


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("请重新登陆!");
printf("</head>\n");

printf("<body>\n");
printf("对不起,请重新登陆。<p>\n");
printf("你长时间没有操作,登陆已经超时。或者是系统发生了错误。<p>\n");
printf("如果是后者,请与管理人员联系。\n");
printf("<!--%s-->",n);
printf("</body>");
printf("</html>\n");
}

 本文Tagssession  
 收藏本文  打印本文  论坛讨论  关闭窗口
· 上一篇:Server Push详解
· 下一篇:怎样利用Perl CGI和LB5K的缺陷攻占远程服务器
· Perl教学 第十二篇 Perl5中的引用之二
· 实战 FastCGI_1.克服 CGI 的瓶颈(2)
· Perl教学 第十篇 格式化输出之四
· Perl教学(13)Perl的面向对象编程之一
· 跟我学Perl(3)


关于本站 | 联系我们 | 业务合作 | 客户案例 | 诚聘英才 | 广告合作 | 收藏本站
海口动网先锋网络科技有限公司版权所有
Copyright © 2000 - 2006 Cndw.Com
中华人民共和国电信与信息服务业务经营许可证编号 琼 ICP 020077