secgateway/Product/user/user_manager/usermanager-auth/user_auth.c

687 lines
17 KiB
C
Raw Normal View History

#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>
#include <cjson/cJSON.h>
#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 (64)
#define UDESIZE (64)
#define UPWDSIZE (64)
typedef struct user_auth
{
unsigned short ID; //用户id
char uname[UNAMESIZE]; //用户名
char udescription[UDESIZE]; //用户描述
unsigned short GID; //用户组ID
char passwd[UPWDSIZE]; //密码
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(AUTH_RECORD.fail_time));
}
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);
cJSON * valid_begin_time = cJSON_GetObjectItem(user_json, "valid_begin_time");
if(!valid_begin_time)
{
if (1 == valid_always->valueint)
{
cJSON_Delete(root);
return false;
}
user_info->valid_begin_time = 0;
}
AUTH_TIME_T2STRING(user_info->valid_begin_time, valid_begin_time->valuestring);
cJSON * valid_end_time = cJSON_GetObjectItem(user_json, "valid_end_time");
if(!valid_end_time)
{
if (1 == valid_always->valueint)
{
cJSON_Delete(root);
return false;
}
user_info->valid_end_time = 0;
}
AUTH_TIME_T2STRING(user_info->valid_end_time, valid_end_time->valuestring);
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 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
// user_info = (USERACCOUNT*)malloc(sizeof(USERACCOUNT));
// memset(user_info, 0, sizeof(USERACCOUNT));
// if (NULL == user_info)
// {
// /* 记录日志 */
// //printf("user_auth()->user_auth->user_info:error. \n");
// auth_result->ret = AUTH_ERR;
// return;
// }
//读取json文件获取数据
// get_from_json(username, user_info);
// if (NULL == user_info)
// {
// auth_result->ret = AUTH_FAIL_PASSWD;
// xfree(user_info);
// return;
// }
/* 数据库查询 */
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、判断在线用户是否到最大值
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;
}
//8、匹配密码
if (0 != strcmp(password, user_info.passwd))
{
auth_result->ret = AUTH_FAIL_PASSWD;
/* 认证失败处理 */
auth_fail_operate(user_id, login_time, config_fail_time);
return;
}
//9、认证成功处理
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;
}
}
}