void doLogin(CImPdu* pPdu, uint32_t conn_uuid) { CImPdu* pPduResp = new CImPdu; IM::Server::IMValidateReq msg; IM::Server::IMValidateRsp msgResp; if(msg.ParseFromArray(pPdu->GetBodyData(), pPdu->GetBodyLength())) { string strDomain = msg.user_name(); string strPass = msg.password(); msgResp.set_user_name(strDomain); msgResp.set_attach_data(msg.attach_data()); do { CAutoLock cAutoLock(&g_cLimitLock); list<uint32_t>& lsErrorTime = g_hmLimits[strDomain]; uint32_t tmNow = time(NULL); //清理超过30分钟的错误时间点记录 /* 清理放在这里还是放在密码错误后添加的时候呢? 放在这里,每次都要遍历,会有一点点性能的损失。 放在后面,可能会造成30分钟之前有10次错的,但是本次是对的就没办法再访问了。 */ auto itTime=lsErrorTime.begin(); for(; itTime!=lsErrorTime.end();++itTime) { if(tmNow - *itTime > 30*60) { break; } } if(itTime != lsErrorTime.end()) { lsErrorTime.erase(itTime, lsErrorTime.end()); } // 判断30分钟内密码错误次数是否大于10 if(lsErrorTime.size() > 10) { itTime = lsErrorTime.begin(); if(tmNow - *itTime <= 30*60) { msgResp.set_result_code(6); msgResp.set_result_string("用户名/密码错误次数太多"); pPduResp->SetPBMsg(&msgResp); pPduResp->SetSeqNum(pPdu->GetSeqNum()); pPduResp->SetServiceId(IM::BaseDefine::SID_OTHER); pPduResp->SetCommandId(IM::BaseDefine::CID_OTHER_VALIDATE_RSP); CProxyConn::AddResponsePdu(conn_uuid, pPduResp); return ; } } } while(false); log("%s request login.", strDomain.c_str()); IM::BaseDefine::UserInfo cUser; if(g_loginStrategy.doLogin(strDomain, strPass, cUser)) { IM::BaseDefine::UserInfo* pUser = msgResp.mutable_user_info(); pUser->set_user_id(cUser.user_id()); pUser->set_user_gender(cUser.user_gender()); pUser->set_department_id(cUser.department_id()); pUser->set_user_nick_name(cUser.user_nick_name()); pUser->set_user_domain(cUser.user_domain()); pUser->set_avatar_url(cUser.avatar_url()); pUser->set_email(cUser.email()); pUser->set_user_tel(cUser.user_tel()); pUser->set_user_real_name(cUser.user_real_name()); pUser->set_status(0); pUser->set_sign_info(cUser.sign_info()); msgResp.set_result_code(0); msgResp.set_result_string("成功"); //如果登陆成功,则清除错误尝试限制 CAutoLock cAutoLock(&g_cLimitLock); list<uint32_t>& lsErrorTime = g_hmLimits[strDomain]; lsErrorTime.clear(); } else { //密码错误,记录一次登陆失败 uint32_t tmCurrent = time(NULL); CAutoLock cAutoLock(&g_cLimitLock); list<uint32_t>& lsErrorTime = g_hmLimits[strDomain]; lsErrorTime.push_front(tmCurrent); log("get result false"); msgResp.set_result_code(1); msgResp.set_result_string("用户名/密码错误"); } } else { msgResp.set_result_code(2); msgResp.set_result_string("服务端内部错误"); } pPduResp->SetPBMsg(&msgResp); pPduResp->SetSeqNum(pPdu->GetSeqNum()); pPduResp->SetServiceId(IM::BaseDefine::SID_OTHER); pPduResp->SetCommandId(IM::BaseDefine::CID_OTHER_VALIDATE_RSP); CProxyConn::AddResponsePdu(conn_uuid, pPduResp); }
void CDBServConn::_HandleValidateResponse(CImPdu* pPdu) { RUNTIME_TRACE; IM::Server::IMValidateRsp msg; CHECK_PB_PARSE_MSG(msg.ParseFromArray(pPdu->GetBodyData(), pPdu->GetBodyLength())); string login_name = msg.user_name(); uint32_t result = msg.result_code(); string result_string = msg.result_string(); CDbAttachData attach_data((uchar_t*)msg.attach_data().c_str(), msg.attach_data().length()); log("HandleValidateResp, user_name=%s, result=%d", login_name.c_str(), result); CImUser* pImUser = CImUserManager::GetInstance()->GetImUserByLoginName(login_name); SpCMsgConn pMsgConn = NULL; if (!pImUser) { log("ImUser for user_name=%s not exist", login_name.c_str()); return; } else { pMsgConn = pImUser->GetUnValidateMsgConn(attach_data.GetHandle()); if (!pMsgConn || pMsgConn->IsOpen()) { log("no such conn is validated, user_name=%s", login_name.c_str()); return; } } if (result != 0) { result = IM::BaseDefine::REFUSE_REASON_DB_VALIDATE_FAILED; } if (result == 0) { IM::BaseDefine::UserInfo user_info = msg.user_info(); uint32_t user_id = user_info.user_id(); CImUser* pUser = CImUserManager::GetInstance()->GetImUserById(user_id); if (pUser) { pUser->AddUnValidateMsgConn(pMsgConn); pImUser->DelUnValidateMsgConn(pMsgConn); if (pImUser->IsMsgConnEmpty()) { CImUserManager::GetInstance()->RemoveImUserByLoginName(login_name); delete pImUser; } } else { pUser = pImUser; } pUser->SetUserId(user_id); pUser->SetNickName(user_info.user_nick_name()); pUser->SetValidated(); CImUserManager::GetInstance()->AddImUserById(user_id, pUser); pUser->KickOutSameClientType(pMsgConn->GetClientType(), IM::BaseDefine::KICK_REASON_DUPLICATE_USER, pMsgConn); auto pRouteConn = get_route_serv_conn(); if (pRouteConn) { IM::Server::IMServerKickUser msg2; msg2.set_user_id(user_id); msg2.set_client_type((::IM::BaseDefine::ClientType)pMsgConn->GetClientType()); msg2.set_reason(1); CImPdu pdu; pdu.SetPBMsg(&msg2); pdu.SetServiceId(SID_OTHER); pdu.SetCommandId(CID_OTHER_SERVER_KICK_USER); pRouteConn->SendPdu(&pdu); } log("user_name: %s, uid: %d", login_name.c_str(), user_id); pMsgConn->SetUserId(user_id); pMsgConn->SetOpen(); pMsgConn->SendUserStatusUpdate(IM::BaseDefine::USER_STATUS_ONLINE); pUser->ValidateMsgConn(pMsgConn->GetHandle(), pMsgConn); IM::Login::IMLoginRes msg3; msg3.set_server_time(time(NULL)); msg3.set_result_code(IM::BaseDefine::REFUSE_REASON_NONE); msg3.set_result_string(result_string); msg3.set_online_status((IM::BaseDefine::UserStatType)pMsgConn->GetOnlineStatus()); IM::BaseDefine::UserInfo* user_info_tmp = msg3.mutable_user_info(); user_info_tmp->set_user_id(user_info.user_id()); user_info_tmp->set_user_gender(user_info.user_gender()); user_info_tmp->set_user_nick_name(user_info.user_nick_name()); user_info_tmp->set_avatar_url(user_info.avatar_url()); user_info_tmp->set_department_id(user_info.department_id()); user_info_tmp->set_email(user_info.email()); user_info_tmp->set_user_real_name(user_info.user_real_name()); user_info_tmp->set_user_tel(user_info.user_tel()); user_info_tmp->set_user_domain(user_info.user_domain()); user_info_tmp->set_status(user_info.status()); CImPdu pdu2; pdu2.SetPBMsg(&msg3); pdu2.SetServiceId(SID_LOGIN); pdu2.SetCommandId(CID_LOGIN_RES_USERLOGIN); pdu2.SetSeqNum(pPdu->GetSeqNum()); pMsgConn->SendPdu(&pdu2); } else { IM::Login::IMLoginRes msg4; msg4.set_server_time(time(NULL)); msg4.set_result_code((IM::BaseDefine::ResultType)result); msg4.set_result_string(result_string); CImPdu pdu3; pdu3.SetPBMsg(&msg4); pdu3.SetServiceId(SID_LOGIN); pdu3.SetCommandId(CID_LOGIN_RES_USERLOGIN); pdu3.SetSeqNum(pPdu->GetSeqNum()); pMsgConn->SendPdu(&pdu3); pMsgConn->Close(); } }
void CDBServConn::_HandleValidateResponse(CImPdu* pPdu) { IM::Server::IMValidateRsp msg; CHECK_PB_PARSE_MSG(msg.ParseFromArray(pPdu->GetBodyData(), pPdu->GetBodyLength())); string login_name = msg.user_name(); uint32_t result = msg.result_code(); string result_string = msg.result_string(); CDbAttachData attach_data((uchar_t*)msg.attach_data().c_str(), msg.attach_data().length()); struct timeval now; gettimeofday(&now, NULL); uint32_t rand_num = rand(); string strKey = int2string(now.tv_usec % 10000) + int2string(now.tv_sec) + int2string(rand_num); strKey += strKey; uint32_t nKeyLen = strKey.length(); if (nKeyLen < 32) { for (uint32_t i=nKeyLen; i<32; i++) strKey += '0'; } else { strKey = strKey.substr(0, 32); } log("HandleValidateResp, user_name=%s, result=%d, key=%s", login_name.c_str(), result, strKey.c_str()); CImUser* pImUser = CImUserManager::GetInstance()->GetImUserByLoginName(login_name); CMsgConn* pMsgConn = NULL; if (!pImUser) { log("ImUser for user_name=%s not exist", login_name.c_str()); return; } else { pMsgConn = pImUser->GetUnValidateMsgConn(attach_data.GetHandle()); if (!pMsgConn || pMsgConn->IsOpen()) { log("no such conn is validated, user_name=%s", login_name.c_str()); return; } log("_HandleValidateResponse, user=%s(%p) conn=%p", login_name.c_str(), pImUser, pMsgConn); } if (result != 0) { result = IM::BaseDefine::REFUSE_REASON_DB_VALIDATE_FAILED; } log("_HandleValidateResponse, login_user=%s key=%s %p ", login_name.c_str(), strKey.c_str(), pMsgConn); total_users++; switch(pMsgConn->GetClientType()) { case IM::BaseDefine::CLIENT_TYPE_WINDOWS: case IM::BaseDefine::CLIENT_TYPE_MAC: pc_total_users++; break; case IM::BaseDefine::CLIENT_TYPE_ANDROID: android_total_users++; break; case IM::BaseDefine::CLIENT_TYPE_IOS: ios_total_users++; break; case IM::BaseDefine::CLIENT_TYPE_WEB: web_total_users++; break; } if (result == 0) { IM::BaseDefine::UserInfo user_info = msg.user_info(); uint32_t user_id = user_info.user_id(); CImUser* pUser = CImUserManager::GetInstance()->GetImUserById(user_id); if (pUser) { log("_HandleValidateResponse, get user %u(%p) key=%s %p", user_id, pUser, strKey.c_str(), pMsgConn); pUser->AddUnValidateMsgConn(pMsgConn); pImUser->DelUnValidateMsgConn(pMsgConn); if (pImUser->IsMsgConnEmpty()) { CImUserManager::GetInstance()->RemoveImUserByLoginName(login_name); delete pImUser; } } else { pUser = pImUser; log("_HandleValidateResponse, use login user %u(%p) key=%s %p", user_id, pUser, strKey.c_str(), pMsgConn); } pUser->SetUserId(user_id); pUser->SetNickName(user_info.user_nick_name()); pUser->SetValidated(); CImUserManager::GetInstance()->AddImUserById(user_id, pUser); log("user_name: %s, uid: %d(%p)", login_name.c_str(), user_id, pMsgConn); pMsgConn->SetKey(strKey); pMsgConn->SetUserId(user_id); pMsgConn->SetOpen(); pMsgConn->SendUserStatusUpdate(IM::BaseDefine::USER_STATUS_ONLINE); CRouteServConn* pRouteConn = get_route_serv_conn(); if (pRouteConn) { IM::Server::IMServerKickUser msg2; msg2.set_user_id(user_id); msg2.set_client_type((::IM::BaseDefine::ClientType)pMsgConn->GetClientType()); msg2.set_reason(1); CImPdu pdu; pdu.SetPBMsg(&msg2); pdu.SetServiceId(SID_OTHER); pdu.SetCommandId(CID_OTHER_SERVER_KICK_USER); pRouteConn->SendPdu(&pdu); } pUser->ValidateMsgConn(pMsgConn->GetHandle(), pMsgConn); //pUser->KickOutSameClientType(pMsgConn->GetClientType(), IM::BaseDefine::KICK_REASON_DUPLICATE_USER, user_id); pUser->KickOutSameClientType(pMsgConn->GetClientType(), IM::BaseDefine::KICK_REASON_DUPLICATE_USER, pMsgConn); IM::Login::IMLoginRes msg3; msg3.set_server_time(time(NULL)); msg3.set_result_code(IM::BaseDefine::REFUSE_REASON_NONE); msg3.set_result_string(result_string); msg3.set_online_status((IM::BaseDefine::UserStatType)pMsgConn->GetOnlineStatus()); msg3.set_client_key(strKey); IM::BaseDefine::UserInfo* user_info_tmp = msg3.mutable_user_info(); user_info_tmp->set_user_id(user_info.user_id()); user_info_tmp->set_user_gender(user_info.user_gender()); user_info_tmp->set_user_nick_name(user_info.user_nick_name()); user_info_tmp->set_avatar_url(user_info.avatar_url()); user_info_tmp->set_sign_info(user_info.sign_info()); user_info_tmp->set_department_id(user_info.department_id()); user_info_tmp->set_email(user_info.email()); user_info_tmp->set_user_real_name(user_info.user_real_name()); user_info_tmp->set_user_tel(user_info.user_tel()); user_info_tmp->set_user_domain(user_info.user_domain()); user_info_tmp->set_status(user_info.status()); user_info_tmp->set_user_type(user_info.user_type()); log("id:%u gender:%u nick:%s avatar:%s sign:%s depid:%u email:%s name:%s tel:%s uname:%s status:%u type:%u", user_info.user_id(), user_info.user_gender(), user_info.user_nick_name().c_str(), user_info.avatar_url().c_str(), user_info.sign_info().c_str(), user_info.department_id(), user_info.email().c_str(), user_info.user_real_name().c_str(), user_info.user_tel().c_str(), user_info.user_domain().c_str(), user_info.status(), user_info.user_type()); CImPdu pdu2; pdu2.SetPBMsg(&msg3); pdu2.SetServiceId(SID_LOGIN); pdu2.SetCommandId(CID_LOGIN_RES_USERLOGIN); pdu2.SetSeqNum(pPdu->GetSeqNum()); pMsgConn->SendPdu(&pdu2); } else { fail_users++; IM::Login::IMLoginRes msg4; msg4.set_server_time(time(NULL)); msg4.set_result_code((IM::BaseDefine::ResultType)result); msg4.set_result_string(result_string); CImPdu pdu3; pdu3.SetPBMsg(&msg4); pdu3.SetServiceId(SID_LOGIN); pdu3.SetCommandId(CID_LOGIN_RES_USERLOGIN); pdu3.SetSeqNum(pPdu->GetSeqNum()); pMsgConn->SendPdu(&pdu3); pMsgConn->Close(); } }