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

447 lines
12 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>
#include <cjson/cJSON.h>
#include "user_auth.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 (127 + 1)
#define UDESIZE (127 + 1)
#define UPWDSIZE (63 + 1)
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 };
/*
* config_lock_time 锁定后-时间,单位(分钟)
* config_fail_num 锁定前-次数
* 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;
}
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;
}
/* 用户认证 */
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; //临时数据,存储登陆用户名对应的用户信息
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;
}
//2、数据库查询配置数据
/*if (false)
{
auth_result->ret = AUTH_FAIL_LACKINFO;
return auth_result;
}*/
config_lock_time = 2;
config_fail_num = 5;
config_fail_time = 40;
/* 校验上述的三个参数都要大于0 */
//3、根据用户名查询用户信息-用户id和用户组id
user_info = (USERACCOUNT*)malloc(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;
}
user_id = user_info->ID;
group_id = user_info->GID;
AUTH_RECORD.group_id = group_id; //更新用户组id
/* 数据库查询 */
/* SELECT idgroup_id FROM `user` WHERE user_name = ""; */
//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;
xfree(user_info);
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;
xfree(user_info);
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;
xfree(user_info);
return;
}
if ((int)(60.0 * config_lock_time) > 60 *remain_lock_time)
{
auth_result->ret = AUTH_FAIL_LOCK;
auth_result->remain_lock_time = remain_lock_time;
xfree(user_info);
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);
xfree(user_info);
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);
xfree(user_info);
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);
xfree(user_info);
return;
}
//9、认证成功处理
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;
xfree(user_info);
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;
}
}
}