#include #include #include #include #include #include #include "user_auth.h" #include "database/database.h" #define NOT_LOCK 0 #define DATA_EMPTY 0 #define AUTH_INIT_FAIL -1 #define AUTH_INIT_SUCCESS 0 #define AUTH_USER_INDEX_MAX (100 + 2) #define UNAMESIZE (63) #define UDESIZE (63) #define UPWDSIZE (63) typedef struct user_auth { unsigned short ID; //用户id char uname[UNAMESIZE+1]; //用户名 char udescription[UDESIZE+1]; //用户描述 unsigned short GID; //用户组ID char passwd[UPWDSIZE+1]; //密码 unsigned short multi_valid; //多人登陆、永久有效 time_t valid_begin_time; //有效期开始时间 time_t valid_end_time; //有效期结束时间 }USERACCOUNT; #define JSON_URL "/nasdata/zhouzian/secogateway/Product/user/user_manager/usermanager-auth/user_json.json" #define AUTH_RECORD (g_user_auth_ret_table[user_id]) #define AUTH_TIME_T2STRING(time_int, time_char) (strftime((time_char), 20, "%Y-%m-%d %H:%M:%S", (localtime(&time_int)))) #define AUTH_STRING2TIME_T(time_char,time_int) \ do { \ struct tm tm_time; \ int res = sscanf(time_char, "%4d-%2d-%2d %2d:%2d:%2d", \ &tm_time.tm_year, &tm_time.tm_mon, &tm_time.tm_mday, \ &tm_time.tm_hour, &tm_time.tm_min, &tm_time.tm_sec); \ tm_time.tm_year -= 1900; \ tm_time.tm_mon--; \ tm_time.tm_isdst = -1; \ time_int = mktime(&tm_time); \ } while (0) #define AUTH_MULTI_MASK 0x0002 #define AUTH_VALID_MASK 0x0001 #define AUTH_MULTI_GET(element) ((element) >> 1) #define AUTH_MULTI_SET(element, value) (((element) & AUTH_VALID_MASK) | (((value) << 1) & AUTH_MULTI_MASK)) #define AUTH_VALID_GET(element) ((element) & AUTH_VALID_MASK) #define AUTH_VALID_SET(element, value) (((element) & AUTH_MULTI_MASK) | ((value) & AUTH_VALID_MASK)) #define xfree(X) \ if(X){ \ free(X); \ X = NULL; \ }; \ /* 定义用户认证结果记录表 */ USER_AUTH_LIST g_user_auth_ret_table[AUTH_USER_INDEX_MAX] = { 0 }; /* * g_config_lock_time 锁定后-时间,单位(分钟) * g_config_fail_num 锁定前-次数 * g_config_fail_time 锁定前-时间,单位(分钟) */ static int g_config_lock_time, g_config_fail_num, g_config_fail_time; /* 创建认证失败时间队列 */ static int init_fail_time_queue(unsigned short user_id, int max_size) { AUTH_RECORD.fail_time = (time_t *)malloc(sizeof(time_t) * max_size); if (NULL == AUTH_RECORD.fail_time) { //记录日志,申请内存失败 return AUTH_INIT_FAIL; } memset(AUTH_RECORD.fail_time, 0, sizeof(time_t) * max_size); AUTH_RECORD.max_size = max_size; return AUTH_INIT_SUCCESS; } /* 清空认证失败时间队列,不释放内存 */ static void empty_fail_time_queue(unsigned short user_id) { if(NULL != AUTH_RECORD.fail_time) { memset(AUTH_RECORD.fail_time, 0, sizeof(time_t) * AUTH_RECORD.max_size); } AUTH_RECORD.front = 0; AUTH_RECORD.rear = 0; AUTH_RECORD.lock_time = 0; } /* 判断队列为空 */ static bool queue_is_empty(unsigned short user_id) { if (AUTH_RECORD.front == AUTH_RECORD.rear) { return true; } return false; } /* 判断队列为满 */ static bool queue_is_full(unsigned short user_id) { if (AUTH_RECORD.front == (AUTH_RECORD.rear + 1) % AUTH_RECORD.max_size) { return true; } return false; } /* 认证失败时间队列删除数据 */ static void de_fail_time_queue(unsigned short user_id) { if (queue_is_empty(user_id)) { return; } AUTH_RECORD.front = (AUTH_RECORD.front + 1) % AUTH_RECORD.max_size; } /* 认证失败时间队列添加数据 */ static void en_fail_time_queue(unsigned short user_id, time_t value) { //满了,删front if (queue_is_full(user_id)) { de_fail_time_queue(user_id); } AUTH_RECORD.fail_time[AUTH_RECORD.rear] = value; AUTH_RECORD.rear = (AUTH_RECORD.rear + 1) % AUTH_RECORD.max_size; return; } /* 认证失败后的处理 */ static void auth_fail_operate(unsigned short user_id, time_t login_time, int config_fail_time) { time_t time_from_front; //单位:秒 //AUTH_RECORD.fail_num++; //计算当前时间到front下标下的时间段,添加当时失败时间到queueu if (queue_is_empty(user_id)) { time_from_front = 0; } else { time_from_front = login_time - AUTH_RECORD.fail_time[AUTH_RECORD.front]; } en_fail_time_queue(user_id, login_time); //队列已经满,且时间小于配置的失败时间,锁定用户 if (queue_is_full(user_id) && (time_from_front < (int)(60.0 * config_fail_time))) { //锁定用户,设置锁定时间 AUTH_RECORD.lock_time = login_time; } } /* 查询json文件数据 */ // static void get_from_json(char *user_name, USERACCOUNT *user_info) // { // FILE* f; // long len; //文件长度 // char* content; //文件内容 // cJSON* root, * user_body; // int array_size; //用户个数 // time_t time_begin = 0; // time_t time_end = 0; // if (NULL == user_name) // { // user_info = NULL; // return; // } // memset(user_info, 0, sizeof(USERACCOUNT)); // f = fopen(JSON_URL, "rb"); // fseek(f, 0, SEEK_END); // len = ftell(f); // fseek(f, 0, SEEK_SET); // content = (char*)malloc(len + 1); // fread(content, 1, len, f); // fclose(f); // root = cJSON_Parse(content); // if (!root) // { // printf("Error before: [%s]\n", cJSON_GetErrorPtr()); // } // array_size = cJSON_GetArraySize(root); // for (int i = 0; i < array_size; i++) // { // user_body = cJSON_GetArrayItem(root, i); // //获取用户名 // char* user_name_temp = cJSON_GetObjectItem(user_body, "user_name")->valuestring; // if (0 == strcmp(user_name, user_name_temp)) // { // /* 转存用户信息,返回 */ // user_info->ID = cJSON_GetObjectItem(user_body, "id")->valueint; // user_info->GID = cJSON_GetObjectItem(user_body, "group_id")->valueint; // user_info->multi_valid = cJSON_GetObjectItem(user_body, "multi_valid")->valueint; // AUTH_STRING2TIME_T(cJSON_GetObjectItem(user_body, "valid_begin_time")->valuestring, time_begin); // AUTH_STRING2TIME_T(cJSON_GetObjectItem(user_body, "valid_end_time")->valuestring, time_end); // user_info->valid_begin_time = time_begin; // user_info->valid_end_time = time_end; // strcpy(user_info->uname, cJSON_GetObjectItem(user_body, "user_name")->valuestring); // strcpy(user_info->passwd, cJSON_GetObjectItem(user_body, "password")->valuestring); // xfree(content); // cJSON_Delete(root); // return; // } // } // /* 未查到用户名,释放内存*/ // xfree(content); // cJSON_Delete(root); // user_info = NULL; // } bool get_config_data(void * auth_hdbc, int * config_data) { int num; if(NULL == auth_hdbc || NULL == config_data) { return false; } char * select_sql = "SELECT locktime config_lock_time, failcount config_fail_num, timehorizon config_fail_time FROM authparas LIMIT 0,1"; char * ret_sql = select_datebase_by_number(20, auth_hdbc, "authparas", select_sql, 1, 0, &num, 0); if(0 == num || NULL == ret_sql) { return false; } cJSON * root = cJSON_Parse(ret_sql); if(!root) { return false; } cJSON * data = cJSON_GetObjectItem(root, "data"); if(!data) { cJSON_Delete(root); return false; } int data_num = cJSON_GetArraySize(data); if (1 != data_num) { cJSON_Delete(root); return false; } cJSON * user_json = cJSON_GetArrayItem(data, 0); if(!user_json) { cJSON_Delete(root); return false; } /* 解析各个数据项 */ cJSON * config_lock_time = cJSON_GetObjectItem(user_json, "config_lock_time"); if(!config_lock_time) { cJSON_Delete(root); return false; } config_data[0] = config_lock_time->valueint; cJSON * config_fail_num = cJSON_GetObjectItem(user_json, "config_fail_num"); if(!config_fail_num) { cJSON_Delete(root); return false; } config_data[1] = config_fail_num->valueint; cJSON * config_fail_time = cJSON_GetObjectItem(user_json, "config_fail_time"); if(!config_fail_time) { cJSON_Delete(root); return false; } config_data[2] = config_fail_time->valueint; return true; } bool get_user_from_database(char* username, void* hdbc, USERACCOUNT* user_info, int* num_sql) { char * ret_sql = NULL; if(NULL == username || NULL == hdbc || NULL == user_info || NULL == num_sql) { return false; } char * select_sql = "SELECT id, group_id, multi_player, valid_always, user_name,password, udescription,valid_begin_time,valid_end_time FROM user_account WHERE user_name = ?"; ret_sql = select_datebase_by_number(20, hdbc, "user_account", select_sql, 1, 0, num_sql, 1, DB_DATA_STRING_TYPE, strlen(username)+1, username); if(0 == *num_sql || NULL == ret_sql) { return true; } /* { "data": [{ "id": 5, "group_id": 5, "multi_player": 0, "valid_always": 0, "user_name": "用户07", "password":"123456", "udescription": "", "valid_begin_time": "", "valid_end_time": "" }] } */ cJSON * root = cJSON_Parse(ret_sql); if(!root) { return false; } cJSON * data = cJSON_GetObjectItem(root, "data"); if(!data) { cJSON_Delete(root); return false; } int data_num = cJSON_GetArraySize(data); if (1 != data_num) { cJSON_Delete(root); return false; } cJSON * user_json = cJSON_GetArrayItem(data, 0); if(!user_json) { cJSON_Delete(root); return false; } /* 解析各个数据项 */ cJSON * id = cJSON_GetObjectItem(user_json, "id"); if(!id) { cJSON_Delete(root); return false; } user_info->ID = id->valueint; cJSON * group_id = cJSON_GetObjectItem(user_json, "group_id"); if(!group_id) { cJSON_Delete(root); return false; } user_info->GID = group_id->valueint; cJSON * user_name = cJSON_GetObjectItem(user_json, "user_name"); if(!user_name) { cJSON_Delete(root); return false; } strcpy(user_info->uname, user_name->valuestring); cJSON * udescription = cJSON_GetObjectItem(user_json, "udescription"); if(!udescription) { strcpy(user_info->udescription, ""); }else { strcpy(user_info->udescription, udescription->valuestring); } cJSON * password = cJSON_GetObjectItem(user_json, "password"); if(!password) { cJSON_Delete(root); return false; } strcpy(user_info->passwd, password->valuestring); cJSON * multi_player = cJSON_GetObjectItem(user_json, "multi_player"); if(!multi_player) { cJSON_Delete(root); return false; } user_info->multi_valid = AUTH_MULTI_SET(user_info->multi_valid, multi_player->valueint); cJSON * valid_always = cJSON_GetObjectItem(user_json, "valid_always"); if(!valid_always) { cJSON_Delete(root); return false; } user_info->multi_valid = AUTH_VALID_SET(user_info->multi_valid, valid_always->valueint); /* 解析、转换有效期开始时间 string2int*/ cJSON * valid_begin_time = cJSON_GetObjectItem(user_json, "valid_begin_time"); if(!valid_begin_time) { cJSON_Delete(root); return false; } if(0 == *valid_begin_time->valuestring) { user_info->valid_begin_time = 0; } else { AUTH_STRING2TIME_T(valid_begin_time->valuestring, user_info->valid_begin_time); } /* 解析、转换有效期结束时间 string2int*/ cJSON * valid_end_time = cJSON_GetObjectItem(user_json, "valid_end_time"); if(!valid_end_time) { cJSON_Delete(root); return false; } if(0 == *valid_end_time->valuestring) { user_info->valid_end_time = 0; } else { AUTH_STRING2TIME_T(valid_end_time->valuestring, user_info->valid_end_time); } cJSON_Delete(root); return true; } /* 用户认证 */ void user_auth_login(char* username, char* password, USER_AUTH_RET *auth_result) { unsigned short user_id, group_id; int init_queue_ret; //初始化循环列表的结果 int user_valid; //数据库中的数据 int user_multi; int config_lock_time = 0; //锁定后的锁定时间,锁定后 int config_fail_num = 0; //规定时间内允许失败的次数,锁定次数,锁定前 int config_fail_time = 0; //规定时间,失败的时间范围,锁定前 time_t login_time; //登陆时间 time_t remain_lock_time; //锁定剩余时间 USERACCOUNT user_info; //临时数据,存储登陆用户名对应的用户信息 void * auth_hdbc; int sql_num; //memset(auth_result, 0, sizeof(USER_AUTH_RET)); login_time = time(NULL); //1、校验用户名和密码 if (NULL == username || NULL == password || 0 == login_time) { auth_result->ret = AUTH_FAIL_INPUT; return; } /* 连接数据库 */ auth_hdbc = connect_database(20); if(NULL == auth_hdbc) { auth_result->ret = AUTH_FAIL_DATABASE; return; } //2、数据库查询配置数据 int config_data[3] = {0,0,0}; bool ret_getconfig = get_config_data(auth_hdbc, config_data); if (!ret_getconfig) { auth_result->ret = AUTH_FAIL_LACKINFO; return; } config_lock_time = config_data[0]; config_fail_num = config_data[1]; config_fail_time = config_data[2]; /* 校验上述的三个参数都要大于0 */ //3、根据用户名查询用户信息-用户id和用户组id /* 数据库查询 */ bool ret_getuser = get_user_from_database(username, auth_hdbc, &user_info, &sql_num); if(!ret_getuser) { auth_result->ret = AUTH_FAIL_DATABASE; return; } if(0 == sql_num) { auth_result->ret = AUTH_FAIL_PASSWD; return; } user_id = user_info.ID; group_id = user_info.GID; //4、初始化用户认证结果记录表对应id内的循环队列 if (DATA_EMPTY == AUTH_RECORD.max_size) { g_config_lock_time = config_lock_time; g_config_fail_time = config_fail_time; g_config_fail_num = config_fail_num; init_queue_ret = init_fail_time_queue(user_id, config_fail_num + 1); if (AUTH_INIT_FAIL == init_queue_ret) { auth_result->ret = AUTH_ERR; return; } } /* 如果用户锁定的配置数据发生修改 */ if (g_config_lock_time != config_lock_time || g_config_fail_time != config_fail_time || g_config_fail_num != config_fail_num) { xfree(AUTH_RECORD.fail_time); g_config_lock_time = config_lock_time; g_config_fail_time = config_fail_time; g_config_fail_num = config_fail_num; init_queue_ret = init_fail_time_queue(user_id, config_fail_num + 1); if (AUTH_INIT_FAIL == init_queue_ret) { auth_result->ret = AUTH_ERR; return; } empty_fail_time_queue(user_id); } //5、判断用户是否锁定 if (NOT_LOCK != AUTH_RECORD.lock_time)//锁定 { remain_lock_time = login_time - AUTH_RECORD.lock_time; if (remain_lock_time < 0) { auth_result->ret = AUTH_FAIL_INPUT; return; } if ((int)(60.0 * config_lock_time) > remain_lock_time) { auth_result->ret = AUTH_FAIL_LOCK; auth_result->remain_lock_time = remain_lock_time; return; } //锁定时间已过,解锁,清空该队列 empty_fail_time_queue(user_id); } //6、判断是否在有效期内 user_valid = AUTH_VALID_GET(user_info.multi_valid); if (1 == user_valid) { if (login_time < user_info.valid_begin_time || login_time > user_info.valid_end_time) { auth_result->ret = AUTH_FAIL_VALID; /* 认证失败处理 */ auth_fail_operate(user_id, login_time, config_fail_time); return; } } //7、判断是否允许多用户登陆 user_multi = AUTH_MULTI_GET(user_info.multi_valid); if(1 == user_multi) { if(1 == AUTH_RECORD.online_num) { auth_result->ret = AUTH_FAIL_MULTI; /* 认证失败处理 */ auth_fail_operate(user_id, login_time, config_fail_time); return; } } //8、判断在线用户是否到最大值(100) if (AUTH_USER_INDEX_MAX - 2 <= AUTH_RECORD.online_num) { auth_result->ret = AUTH_FAIL_OVER; /* 认证失败处理 */ auth_fail_operate(user_id, login_time, config_fail_time); return; } //9、匹配密码 if (0 != strcmp(password, user_info.passwd)) { auth_result->ret = AUTH_FAIL_PASSWD; /* 认证失败处理 */ auth_fail_operate(user_id, login_time, config_fail_time); return; } //10、认证成功处理 AUTH_RECORD.group_id = group_id; //更新用户组id empty_fail_time_queue(user_id); AUTH_RECORD.online_num++; auth_result->ret = AUTH_SUCCESS; auth_result->user_id = user_id; auth_result->group_id = group_id; disconnect_database(20, auth_hdbc); return; } /* 用户下线数-1 */ void reduce_online_num(unsigned short user_id) { if(AUTH_RECORD.online_num > 0) { AUTH_RECORD.online_num--; } } /* 用户在线节点重置-按用户id */ void reset_online_by_userid(int *user_ids, int num) { if(NULL == user_ids || 0 == num) { return; } int user_id_temp = 0; for(int i = 0; i < num; i++) { user_id_temp = user_ids[i]; if(0 != user_ids[i]) { empty_fail_time_queue(user_id_temp); g_user_auth_ret_table[user_id_temp].fail_time = 0; g_user_auth_ret_table[user_id_temp].group_id = 0; g_user_auth_ret_table[user_id_temp].max_size = 0; g_user_auth_ret_table[user_id_temp].online_num = 0; } } } /* 用户在线节点重置-按用户组id */ void reset_online_by_groupid(int *group_ids) { if(NULL == group_ids) { return; } unsigned short group_id_temp = 0; for(int i = 0; i < AUTH_USER_INDEX_MAX; i++) { group_id_temp = g_user_auth_ret_table[i].group_id; if(0 != group_id_temp && group_id_temp == group_ids[group_id_temp]) { empty_fail_time_queue(i); g_user_auth_ret_table[i].fail_time = 0; g_user_auth_ret_table[i].group_id = 0; g_user_auth_ret_table[i].max_size = 0; g_user_auth_ret_table[i].online_num = 0; } } }