通常網路密碼驗證過程是這樣的:用戶端在獲取使用者輸入的用戶名和密碼資訊之後創建socket通訊端與遠端伺服器建立一個連接,發送用戶名和密碼並等待伺服器返回消息,伺服器收到用戶名和密碼之後查詢伺服器資料庫,如果用戶名密碼正確返回給用戶端一個登錄成功消息,否則返回一個密碼錯誤的消息!
下面是用VC++實現驗證過程中的部分代碼,代碼有點亂:
//獲取使用者輸入資訊
void CClientDlg::OnOK()
{
//之前socket已經經過初始化
UpdateData();
if(m_username.IsEmpty()||m_userID.IsEmpty())
MessageBox("請輸入所有資訊!","用戶登錄",MB_OK);
else
{
if(Load()) //調用驗證函數
{
// close(destSocket);
closesocket(destSocket);
CDialog::OnOK();
MessageBox("登陸成功!","用戶登錄",MB_OK);//驗證成功
CChat chat;
chat.m_username=m_username;
// chat.res=res;
chat.DoModal();
}
else
{ //驗證失敗
MessageBox("尚未註冊或\n用戶名/密碼有誤。","用戶登錄",MB_OK);
}
}
}
BOOL CClientDlg::Load() //發送"Load:"
{
////////////////////////發送登陸資訊並接收回饋資訊/////////////////////////////
char sendText[100],recvText[5025];
int numsnt,numrcv,status;
sprintf(sendText,"Load:%s,%s",m_username,m_userID);
numsnt=send(destSocket, sendText, strlen(sendText) + 1, NO_FLAGS_SET);
if (numsnt != (int)strlen(sendText) + 1)
{
MessageBox("ERROR: Connection terminated!","用戶登錄",MB_OK);
status=closesocket(destSocket);
if (status == SOCKET_ERROR)
MessageBox("ERROR: closesocket unsuccessful!","用戶登錄",MB_OK);
status=WSACleanup();
if (status == SOCKET_ERROR)
MessageBox("ERROR: WSACleanup unsuccessful!","用戶登錄",MB_OK);
return false;
}
numrcv=recv(destSocket, recvText, 5025, NO_FLAGS_SET);
if ((numrcv == 0) || (numrcv == SOCKET_ERROR))
{
MessageBox("ERROR: Connection terminated!","用戶登錄",MB_OK);
status=closesocket(destSocket);
if (status == SOCKET_ERROR)
MessageBox("ERROR: closesocket unsuccessful!","用戶登錄",MB_OK);
status=WSACleanup();
if (status == SOCKET_ERROR)
MessageBox("ERROR: WSACleanup unsuccessful!","用戶登錄",MB_OK);
return false;
}
recvText[numrcv]='\0';
//////////////////////////////////////////////////////////////////////////////
/////////////////////讀取返回標誌和使用者資訊///////////////////////////////////
char Flag[10];
char *pos=strchr(recvText,'!');
pos+=1;
int len_text=strlen(recvText);
int len_pos=strlen(pos);
int len=len_text-len_pos;
for(int i=0;i<len;i++)
Flag[i]=recvText[i];
Flag[len]='\0';
if(strcmp(Flag,"success!")!=0)
return false;
///////////////////////////////////////////////////////////////////////////////
///////////////////////將使用者資訊寫入與用戶名對應的檔////////////////////////
else
{
CString filename;
filename.Format(".\\data\\%s.db",m_username);
FILE *file;
if((file=fopen(filename,"w"))!=NULL)
{
fprintf(file,"%s",pos);
}
fclose(file);
}
///////////////////////////////////////////////////////////////////////////////
return true;
}
//附網路初始化代碼
BOOL CClientDlg::Init_net()
{
/////////////////////////網路初始化///////////////////////////////////
status=WSAStartup(MAKEWORD(1, 1), &Data);
if (status != 0)
MessageBox("ERROR: WSAStartup unsuccessful!","用戶登錄",MB_OK);
destAddr=inet_addr(DEST_IP_ADDR); //暫時定為本機使用
memcpy(&destSockAddr.sin_addr, &destAddr,sizeof(destAddr));
destSockAddr.sin_port=htons(606);
destSockAddr.sin_family=AF_INET;
destSocket=socket(AF_INET, SOCK_STREAM, 0);
if (destSocket == INVALID_SOCKET)
{
MessageBox("ERROR: socket unsuccessful!","用戶登錄",MB_OK);
status=WSACleanup();
if (status == SOCKET_ERROR)
MessageBox("ERROR: WSACleanup unsuccessful!","用戶登錄",MB_OK);
return false;
}
//////////////////////////////////////////////////////////////////////
///////////////////////////連接網路////////////////////////////////////////////
status=connect(destSocket, (LPSOCKADDR) &destSockAddr,sizeof(destSockAddr));
if (status == SOCKET_ERROR)
{
MessageBox("ERROR: connect unsuccessful!","用戶登錄",MB_OK);
status=closesocket(destSocket);
if (status == SOCKET_ERROR)
MessageBox("ERROR: closesocket unsuccessful!","用戶登錄",MB_OK);
status=WSACleanup();
if (status == SOCKET_ERROR)
MessageBox("ERROR: WSACleanup unsuccessful!","用戶登錄",MB_OK);
return false;
}
///////////////////////////////////////////////////////////////////////////////
return true;
}
//////////////////////////////////服務端代碼/////////////////////////////////
//建立一個基於消息的非同步通訊端
BOOL CSkyQQsrvDlg::InitSocket()
{
m_socket=WSASocket(AF_INET,SOCK_DGRAM,0,NULL,0,0); //WSASocket創建通訊端
if(INVALID_SOCKET==m_socket)
{
MessageBox("創建通訊端失敗!");
return FALSE;
}
SOCKADDR_IN addrSock;
addrSock.sin_addr.S_un.S_addr=htonl(INADDR_ANY);
addrSock.sin_family=AF_INET;
addrSock.sin_port=htons(606);//設置606為監聽埠
if(SOCKET_ERROR==bind(m_socket,(SOCKADDR*)&addrSock,sizeof(SOCKADDR)))
{
MessageBox("綁定失敗!");
return FALSE;
}
if(SOCKET_ERROR==WSAAsyncSelect(m_socket,m_hWnd,UM_SOCK,FD_READ))//請求一個基於消息的網路事件通知非同步通訊端
{
MessageBox("註冊網路讀取事件失敗!");
return FALSE;
}
return TRUE;
}
//建立消息映射,在SkyQQsrvDlg.h中添加
#define UM_SOCK WM_USER+1 //定義消息
//消息映射
BEGIN_MESSAGE_MAP(CSkyQQsrvDlg, CDialog)
//{{AFX_MSG_MAP(CSkyQQsrvDlg)
// ON_WM_SYSCOMMAND()
// ON_WM_PAINT()
// ON_WM_QUERYDRAGICON()
ON_MESSAGE(UM_SOCK,OnSock)
// ON_BN_CLICKED(IDC_BTN_SEND, OnBtnSend)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
BOOL bchar=FALSE;//密碼檢測結果
SOCKET m_socket;
void CSkyQQsrvDlg::OnSock(WPARAM wParam,LPARAM lParam)
{
switch(LOWORD(lParam))
{
case FD_READ: //讀取事件
WSABUF wsabuf;
wsabuf.buf=new char[200];
wsabuf.len=200;
DWORD dwRead;
DWORD dwFlag=0;
SOCKADDR_IN addrFrom;
int len=sizeof(SOCKADDR);
CString str;
CString strTemp;
HOSTENT *pHost;
if(SOCKET_ERROR==WSARecvFrom (m_socket,&wsabuf,1,&dwRead,&dwFlag,//WSARecvFrom接受資料函數
(SOCKADDR*)&addrFrom,&len,NULL,NULL))
{
MessageBox("接收資料失敗!");
return;
}
pHost=gethostbyaddr((char*)&addrFrom.sin_addr.S_un.S_addr,4,AF_INET);
addrFromIP.sin_addr.S_un.S_addr=addrFrom.sin_addr.S_un.S_addr;
char(wsabuf.buf);//調用密碼檢測函數
CString strSend;
if(bchar)
{//發送驗證成功的消息
strsend="success";
}
else strsend="FALSE";
SOCKADDR_IN addrTo;
addrTo.sin_family=AF_INET;
addrTo.sin_addr.S_un.S_addr=addrFromIP.sin_addr.S_un.S_addr;
addrTo.sin_port=Port;//將獲取的資料埠設置為發送資料埠
len=strSend.GetLength(); //長度
wsabuf.buf=strSend.GetBuffer(len);
wsabuf.len=len+1;
if(SOCKET_ERROR==WSASendTo(m_socket,&wsabuf,1,&dwSend,0, //WSASend發送資料
(SOCKADDR*)&addrTo,sizeof(SOCKADDR),NULL,NULL))
{
MessageBox("發送資料失敗!");
return;
}
}
}
void char(char * wsabuf)
{
_ConnectionPtr m_pConnection;
_RecordsetPtr m_pRecordset
CString admin,passwd;
huanyuan(wsabuf,admin,passwd);
//假設伺服器上已經有一個ACCESS資料庫檔,檔案名為skywd,並建有user(admin,password)表
//初始話OLE/COM庫環境
::CoInitialize(NULL);
try
{
_ConnectionPtr pConn(__uuidof(Connection));
pConn->C;
pConn->Open("","","",adConnectUnspecified); //打開對資料庫的連接,使用者ID和密碼,同步打開這個連接
m_pC;
}
//捕捉異常
catch(_com_error e)
{ //顯示錯誤資訊
// AfxMessageBox(e.Description());
AfxMessageBox("資料庫連接出錯");
}
//設置INSERT語句,查詢資料
_bstr_t vSQL;
vSQL = "SELECT * FROM user WHERE admin = '" +admin + "'" ; //變數直接加,字串用""括起來
try
{
m_pRecordset.CreateInstance(__uuidof(Recordset));
m_pRecordset->Open(vSQL,m_pConnection.GetInterfacePtr(), //直接用記錄集物件查詢
adOpenDynamic,adLockOptimistic,adCmdText);
}
catch(_com_error e)
{
AfxMessageBox(e.Description());
}
_variant_t var = m_pRecordset->GetCollect("password");
if(var.vt!=VT_NULL)
{
if(passwd==(LPCTSTR)_bstr_t(var))
bchar=TRUE;//通過驗證
}
else
{ //如果答案為空,則重建答案
bchar=FALSE;
}
//斷開資料庫連接
if(m_pRecordset!=NULL)
m_pRecordset->Close();
m_pConnection->Close();
}
zhuanhuan(char * wsabuf,CString admin,CString passwd)
{
CString str1=wsabuf;
int n1=str1.Find(":");
int n2=str1.Find(",");
int n3=str1.Getlength()-1;
admin=str1.Left(n2);
admin=admin.Right(n2-n1-1);
passwd=str1.Right(n3-n2-1);
}
我也有在寫MFC ,歡迎一起來交流
回覆刪除