一 客户端进行登录前期工作
包括,登录验证,向服务器发送登录请求
运行程序,显示登录页面
如果是自动登录,则加载本地账号,进行登录
if (cbox_autoLogin_->IsSelected()){
char szAccount[32] = { 0 }, szPasswd[40] = { 0 };
xnw_loadAccount(szAccount, szPasswd);
if (*szAccount && *szPasswd) {
user_name_edit_->SetUTF8Text(szAccount);
password_edit_->SetUTF8Text(szPasswd);
DoBeforeLogin();
}
}
开始登录之前的验证,验证账号密码是否为空:
void LoginForm::DoBeforeLogin()
{
switch (login_tab_->GetCurSel())
{
case 0://账号密码方式
{
std::string username = user_name_edit_->GetUTF8Text();
StringHelper::Trim(username);
std::wstring user_name_temp = nbase::UTF8ToUTF16(username);
user_name_temp = StringHelper::MakeLowerString(user_name_temp);
username = nbase::UTF16ToUTF8(user_name_temp);
if (username.empty())
{
ShowLoginTip(L"帐号为空");
return;
}
std::string password = password_edit_->GetUTF8Text();
StringHelper::Trim(password);
if (password.empty())
{
ShowLoginTip(L"密码为空");
return;
}
StartLogin(username, password);
}
break;
case 1: //验证码方式
{
std::string userPhone = user_phone_edit_->GetUTF8Text();
StringHelper::Trim(userPhone);
std::wstring user_Phone_temp = nbase::UTF8ToUTF16(userPhone);
user_Phone_temp = StringHelper::MakeLowerString(user_Phone_temp);
userPhone = nbase::UTF16ToUTF8(user_Phone_temp);
if (userPhone.empty())
{
ShowLoginTip(L"请输入手机号或邮箱");
return;
}
std::string verifyCode = verifyCode_edit_->GetUTF8Text();
StringHelper::Trim(verifyCode);
if (verifyCode.empty())
{
ShowLoginTip(L"验证码为空");
return;
}
StartLoginCode(userPhone, verifyCode);
}
}
}
正式进行登录,向服务器发送登录信息,由服务器判断登录是否成功
void LoginForm::StartLogin( std::string username, std::string password )
{
user_name_edit_->SetEnabled(false);
password_edit_->SetEnabled(false);
login_error_tip_->SetVisible(false);
login_ing_tip_->SetVisible(true);
btn_login_->SetVisible(false);
//btn_cancel_->SetVisible(true);
xnw_Login(username.c_str(), password.c_str());
}
void LoginForm::StartLoginCode(std::string username, std::string code)
{
user_name_edit_->SetEnabled(false);
password_edit_->SetEnabled(false);
login_error_tip_->SetVisible(false);
login_ing_tip_->SetVisible(true);
btn_login_->SetVisible(false);
//btn_cancel_->SetVisible(true);
xnw_LoginByCode(username.c_str(), code.c_str());
}
int xnw_Login(const char* account,const char* pass)
{
CFormData form;
form.AddPair("account", account);
form.AddPair("password", pass);
return xnw_api_request("/v1/weibo/do_login", form, g_ui.GetHwnd());
}
int xnw_LoginByCode(const char* account, const char* code)
{
CFormData form;
form.AddPair("account", account);
form.AddPair("code", code);
return xnw_api_request("/v1/weibo/do_login", form, g_ui.GetHwnd());
}
二 服务器回应
总的流程大致这样:
cb_api_resp中,服务器返回登录信息,
在,g_ui.callback(cbitem->hWnd, cbitem->uMsg, cbitem->wParam, p); 处理服务器返回的登录信息,
根据登录信息,发送 WM_LAVAAGNT_MSG 自定义消息,在窗口自定义消息中,具体处理登录反馈 on_login_resp
1) 总的服务器回应处理
static void cb_api_resp(void* param, int code, CHttpResponseParse* resp)
{
CUICallbackItem* cbitem = (CUICallbackItem*)param;
if (cbitem->uMsg == WPARAM_DOWNLOAD_FILE) {
g_downMgr.cb_down_resp(param, code, resp);
return;
}
const char* p = NULL;
CBinBuf bf;
if (resp) {
if (resp->m_header.m_code == 302) {
CBinBuf bfV;
p = resp->m_header.GetHeaderValue("location",bfV);
bf.Format("{");
int bComma = 0;
CJsonObj::append_json_item(bf, "location", p, bComma);
bf.AppendFormat("}");
p = bf.c_str();
}
else {
int len;
p = resp->GetRawContent(bf, len);
}
}
g_ui.callback(cbitem->hWnd, cbitem->uMsg, cbitem->wParam, p);
delete cbitem;
}
登录回应
return xnw_api_request("/v1/weibo/do_login", form, g_ui.GetHwnd());
因为登录时,向服务器发出的请求是这么写的,服务器处理返回时,也带一个窗口句柄信息,由这个窗口负责处理。
static void cb_api_resp(void* param, int code, CHttpResponseParse* resp)
{
CUICallbackItem* cbitem = (CUICallbackItem*)param;
...
}
class CUICallbackItem
{
public:
HWND hWnd;
UINT uMsg;
WPARAM wParam;
char url[128];
CUICallbackItem(HWND h, UINT u, WPARAM w=NULL, const char* _url=NULL) {
hWnd = h;
uMsg = u;
wParam = w;
strcpyN(url, _url, sizeof(url));
}
};
因为登录传送的是g_ui窗口,所以应该由g_ui窗口负责登录信息处理。
这里注意:
CThreadToUI::DefWndProc中,有一个登录处理:on_login_resp(wParam, (CJsonObj*)lParam);
CThreadToUI::callback中也有一个登录处理:if (hWnd == m_hWnd && !code),
如果是g_ui窗口,且body存在的话,则登录成功,
body不存在,则登录失败。
不管成功与失败,都调用login_resp,在login_resp中,向窗口发送WM_LAVAAGNT_MSG, 在消息窗口处理函数DefWndProc中,处理这个消息,对应于登录消息,就是处理on_login_resp(wParam, (CJsonObj*)lParam);
static CThreadToUI g_ui;
static CXnwDownloadMgr g_downMgr;
void CThreadToUI::callback(HWND hWnd, int code, WPARAM wParam, const char* body)
{
if (hWnd == m_hWnd && !code) {
if (body) {
CJsonObj json(body);
int err = json.getInt("errcode", 0);
std::string s, sUid,name;
if (err != 0) {
json.getString("msg", s);
login_resp(XNW_ERR_API_AUTH, new CJsonObj(body));
return;
}
json.getString("account", name);
json.getString("uid", sUid);
json.getString("passport", s);
login_resp(XNW_ERR_OK);
// if dynamic code login ok.
std::string sPasswd;
json.getString("oldpasswd", sPasswd);
if (sPasswd.length()) {
xnw_saveAccount(name.c_str(), sPasswd.c_str());
}
if (g_myLavaAgnt) {
g_myLavaAgnt->Login(sUid.c_str(), s.c_str(), "<d pc=\"1\"/>", 0, 1, 2);
}
}
else {
login_resp(XNW_ERR_API);
}
return;
}
CJsonObj* p = NULL;
if (body) {
p = new CJsonObj(body);
{
std::wstring bodyS = nbase::UTF8ToUTF16(body);
std::string bodyA = MyString::wstos(bodyS);
m_lavaError.WriteSuccessFuc("-------------服务器传来信息如下:-----------------\n");
m_lavaError.WriteSuccessFuc(bodyA);
}
}
if (!callui(hWnd, code, (LPARAM)p)) {
if(p) delete p;
}
else{
std::string info;
CHAR capital[256];
info.append("窗口:");
GetWindowTextA(hWnd, capital, 256);
info.append(capital);
m_lavaError.WriteSuccessFuc(info, handleMsg);
}
}
根据服务器返回的登录信息, 发送窗口消息,WM_LAVAAGNT_MSG
void login_resp(int code,CJsonObj* p=NULL) {
callui(m_hWnd, code, (LPARAM)p);
}
int callui(HWND hWnd, WPARAM wParam, LPARAM lParam=NULL) {
for (int n = 3; n > 0; --n) {
if (PostMessage(hWnd, WM_LAVAAGNT_MSG, wParam, lParam))
{
return 1;
}
}
return 0;
}
在窗口消息中,具体处理登录反馈:on_login_resp
class CThreadToUI
: public CWndX
{
LRESULT DefWndProc(UINT uMsg, WPARAM wParam, LPARAM lParam) {
if (uMsg == WM_LAVAAGNT_MSG) {
if (wParam == WPARAM_OPEN_LIVE) {
CJsonObj* pJson = (CJsonObj*)lParam;
if (pJson) {
std::string s1,s2;
pJson->getString("push", s1);
pJson->getString("name", s2);
show_liveroom(s1,s2);
delete pJson;
}
return 0;
}
else if (wParam == WPARAM_OPEN_PLAYER) {
CJsonObj* pJson = (CJsonObj*)lParam;
if (pJson) {
std::string s1, s2;
pJson->getString("pull", s1);
pJson->getString("name", s2);
show_player(s1, s2);
delete pJson;
}
return 0;
}
else {
on_login_resp(wParam, (CJsonObj*)lParam);
}
}
return DefWindowProc(m_hWnd, uMsg, wParam, lParam);
}
int callui(HWND hWnd, WPARAM wParam, LPARAM lParam=NULL) {
for (int n = 3; n > 0; --n) {
if (PostMessage(hWnd, WM_LAVAAGNT_MSG, wParam, lParam))
{
return 1;
}
}
return 0;
}
public:
HWND GetHwnd() const {
return m_hWnd;
}
void login_resp(int code,CJsonObj* p=NULL) {
callui(m_hWnd, code, (LPARAM)p);
}
void callback(HWND hWnd, int code, WPARAM wParam, const char* body);
};
具体的登录处理
void on_login_resp(int code,CJsonObj* pJson)
{
LoginForm* form = (LoginForm*)nim_comp::WindowsManager::GetInstance()->GetWindow(LoginForm::kClassName, LoginForm::kClassName);
if (form) {
std::string s;
if (pJson) {
pJson->getString("msg", s);
delete pJson;
}
form->OnLoginResult(code,s);
if (code == XNW_ERR_PRESENCE_OK) {
//show_courselist();
show_myClass();
form->ShowWindow(false);
form->Close(0);
}
else if (code == XNW_ERR_UPDATA) //新版本强制更新 -9999
{
pJson->getString("msg", s);
//
//
}
}
}