專案實戰篇-餐館管理系統—MFC,PHP,MySql:2.登陸功能的實現
阿新 • • 發佈:2019-02-08
1.mysql 資料庫的建立
首先在虛擬機器終端上利用 ifconfig 獲取虛擬機器IP。
然後在本地計算機瀏覽器位址列輸入 http://192.168.200.128/phpmyadmin 如果載入不成功檢查Ubuntu是否安裝phpmyadmin。
輸入mysql的賬號和密碼進入。並且新建一個名為 sdb 的資料庫
及其對應的表:
privilege
users
2.後端PHP程式碼
db_info.php
<?php
/**
* Created by PhpStorm.
* User: pldq
* Date: 16-12-13
* Time: 下午8:31
*/
#echo "From db_info.php";
# databases infomation
static $DB_HOST="localhost";
static $DB_NAME="sdb";
static $DB_USER="root";
static $DB_PASS="******";
global $con;
$con = mysqli_connect($DB_HOST, $DB_USER, $DB_PASS);
if ($con == null) {
die("FAILED|Could not connect:" . mysqli_error() . "<br>" );
}
if (!mysqli_select_db($con, "sdb")) {
die("FAILED|Could't use foo: " . mysqli_error());
}
?>
login.php
<?php
session_start();
require_once ('db_info.php');
// echo "Hello World!";
// echo $_REQUEST["username"];
// echo $_REQUEST["psd"];
$username = $_POST["username" ];
$psd = $_POST["psd"];
// $phone = $_POST["phone"];
// $email = $_POST["email"];
$sql_username = "Select * from users WHERE username = '" . $username . "'";
$mysqli_result = mysqli_query($con, $sql_username);
$row = mysqli_fetch_array($mysqli_result);
if (mysqli_num_rows($mysqli_result) == 0) {
die("FAILED|The username is not existed!");
}
if ($row['password'] === $psd and strlen($psd) > 6)
{
$str_ret = "SUCCEED|SUCCEED LOGIN IN THE SYSTEM!|";
$sql_get_privilege = "Select * from privilege WHERE username = '" . $username . "'";
$mysqli_privilege_result = mysqli_query($con, $sql_get_privilege);
if (mysqli_num_rows($mysqli_result) == 0) {
$_SESSION['user'] = $username;
die($str_ret);
} else {
$row = mysqli_fetch_array($mysqli_privilege_result);
$_SESSION['user'] = $username;
$_SESSION['rightstr'] = $row['rightstr'];
die($str_ret . $row['rightstr']);
}
} else {
die("FAILED|The password is incorrect!");
}
mysqli_close($con); // close db connect
?>
然後將程式碼上傳到Ubuntu 站點目錄下
這樣網頁後端就編寫成功了!
3.MFC 端
1、利用 MFC 生成嚮導生成一個基於對話方塊的程式。
使用GDI繪圖:
#include <gdiplus.h>
#pragma comment(lib, "gdiplus.lib")
using namespace Gdiplus;
// Bitmap* m_mainImage; // 宣告為類成員
BOOL CManagementSystemDlg::OnInitDialog()
{
// 初始化 GDI+
GdiplusStartupInput gdiplusStartupInput;
GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL);
// !其餘程式碼沒有進行修改、刪除
}
void CManagementSystemDlg::OnClose()
{
// 釋放GDI+
GdiplusShutdown(m_gdiplusToken);
}
繪製圖片:
#define IMAGE_MAIN_FILENAME L"Important\\res_login\\main.jpg"
BOOL CManagementSystemDlg::OnInitDialog()
{
// 載入圖片到記憶體
m_mainImage = Bitmap::FromFile(IMAGE_MAIN_FILENAME);
}
void CManagementSystemDlg::OnPaint()
{
CClientDC Clientdc(this);
Graphics graphics(Clientdc.GetSafeHdc());
// 繪製圖片
graphics.DrawImage(m_mainImage, 0, 0, m_mainImage->GetWidth(), m_mainImage->GetHeight());
}
然後編譯執行、、、
但是執行後發現視窗並不能實現拖動。為了實現視窗拖動我們還需要讓對話方塊響應 WM_NCHITTEST 訊息。讓它把點選再視窗客戶區的訊息響應為在標題欄點選的訊息。
LRESULT CManagementSystemDlg::OnNcHitTest(CPoint point)
{
// TODO: 在此新增訊息處理程式程式碼和/或呼叫預設值
CRect rc;
GetClientRect(&rc);
ClientToScreen(&rc);
int x = point.x;
int y = point.y;
if (x >= rc.left && x <= rc.right && y >= rc.top && y <= rc.bottom)
{
return HTCAPTION;
}
else {
return CDialogEx::OnNcHitTest(point);
}
}
退出按鈕的事件程式碼:
void CManagementSystemDlg::OnBnClickedButtonExit()
{
// TODO: 在此新增控制元件通知處理程式程式碼
this->SendMessage(WM_CLOSE, 0, 0);
}
登陸按鈕的事件程式碼:
HTTP訪問:
1. 利用MFC 裡面的CSession、CHttpConnection等函式:(實現失敗!)
#include <afxinet.h>
void Ansi2Wchar(std::string strSource, CString& strDest)
{
int length = 0;
length = ::MultiByteToWideChar(CP_ACP, 0, strSource.c_str(), strSource.length(), 0, 0);
WCHAR* Buffer = new WCHAR[length + 1];
memset(Buffer, 0, (length + 1) * sizeof(WCHAR));
::MultiByteToWideChar(CP_ACP, 0, strSource.c_str(), strSource.length(), Buffer, length);
strDest = Buffer;
delete[] Buffer;
}
void Wchar2Ansi(CString strSource, std::string& strDest)
{
int length = 0;
length = ::WideCharToMultiByte(CP_ACP, 0, strSource.GetBuffer(), strSource.GetLength(), 0, 0, 0, 0);
strSource.ReleaseBuffer();
CHAR* Buffer = new CHAR[length + 1];
memset(Buffer, 0, sizeof(CHAR)* (length + 1));
::WideCharToMultiByte(CP_ACP, 0, strSource.GetBuffer(), strSource.GetLength(), Buffer, length, 0, 0);
strSource.ReleaseBuffer();
strDest = Buffer;
delete[] Buffer;
}
void CManagementSystemDlg::OnBnClickedButtonLogin()
{
// TODO: 在此新增控制元件通知處理程式程式碼
UpdateData(TRUE);
CString strUrl = L"http://192.168.200.128/myAdminSystem/login.php";
DWORD dwServiceType = AFX_INET_SERVICE_HTTP;
CString strServer = L"";
CString strObject = L"";
INTERNET_PORT nPort = 80;
if (!AfxParseURL(strUrl, dwServiceType, strServer, strObject, nPort))
{
return;
}
CInternetSession mysession(L"session", 0);
mysession.SetOption(INTERNET_OPTION_CONNECT_TIMEOUT, 1000 * 20);
mysession.SetOption(INTERNET_OPTION_CONNECT_BACKOFF, 1000);
mysession.SetOption(INTERNET_OPTION_CONNECT_RETRIES, 1);
CHttpConnection* mycon = mysession.GetHttpConnection(strServer, INTERNET_FLAG_KEEP_CONNECTION, nPort);
CHttpFile* myfile = mycon->OpenRequest(CHttpConnection::HTTP_VERB_POST, strObject, 0, 1, 0, L"HTTP/1.1", INTERNET_FLAG_RELOAD | INTERNET_FLAG_DONT_CACHE);
CString strPostData = L"username=" + strUSER + L"&psd=" + strPsd;
std::string strPost = "";
Wchar2Ansi(strPostData, strPost);
CString strHeaders = L"Content-Type: application/x-www-form-urlencoded\r\nAccept: */*\r\n";
BOOL result = myfile->SendRequest(strHeaders, (LPVOID)strPost.c_str(), strPost.size());
strHeaders.ReleaseBuffer();
strPostData.ReleaseBuffer();
CHAR Buffer[1024 + 1] = { 0 };
memset(Buffer, 0, (1024 + 1) * sizeof(CHAR));
std::string strRawResponse = "";
UINT nReaded = 0;
while ((nReaded = myfile->Read((void*)Buffer, 1024)) > 0)
{
Buffer[nReaded] = '\0';
strRawResponse += Buffer;
memset(Buffer, 0, (1024 + 1) * sizeof(CHAR));
}
CString strResponse = L"";
Ansi2Wchar(strRawResponse, strResponse);
if (strResponse.GetLength() <= 0)
{
MessageBox(L"獲取資料失敗!", L"Info", MB_OK | MB_ICONWARNING);
return;
}
}
這個 Bug 很奇怪,當我開啟 Fiddler 進行抓包時 SendRequest 可以成功使用,當我關閉 Fiddler 的抓包功能時它會彈出 “無法與伺服器建立連線的資訊框”
2. 利用WinHttp 的 com 元件智慧指標程式設計(實現簡單、現使用)
#import "C:\\windows\\system32\\winhttp.dll"
#define STRING_LOGIN_HOST_ADDRESS L"http://192.168.200.128/myAdminSystem/login.php"
void CManagementSystemDlg::OnBnClickedButtonLogin()
{
// TODO: 在此新增控制元件通知處理程式程式碼
UpdateData(TRUE);
CString strPostData = L"username=" + strUSER + L"&psd=" + strPsd;
// using com programming winhttp
WinHttp::IWinHttpRequestPtr ptrHttp = nullptr;
ptrHttp.CreateInstance(__uuidof(WinHttp::WinHttpRequest));
if (0 != ptrHttp->Open(L"POST", STRING_LOGIN_HOST_ADDRESS))
{
MessageBox(L"伺服器連線失敗!", L"Info", MB_OK | MB_ICONSTOP);
return;
}
ptrHttp->SetRequestHeader(L"User-Agent", L" Mozilla / 5.0 (Windows NT 6.1; WOW64) AppleWebKit / 537.36 (KHTML, like Gecko) Chrome / 50.0.2661.102 Safari / 537.36");
ptrHttp->SetRequestHeader(L"Content-Type", L"application/x-www-form-urlencoded");
ptrHttp->Send(strPostData.GetBuffer());
strPostData.ReleaseBuffer();
CString strResult = ptrHttp->GetResponseText();
CString strCookie = ptrHttp->GetResponseHeader(L"Set-Cookie"); // get http post cookie
strCookie.Replace(L"; path=/", L"");
}
對HTTP返回訊息的處理:
if (strResult.GetLength() <= 0)
{
MessageBox(L"獲取資料失敗!", L"Info", MB_OK | MB_ICONWARNING);
return;
}
if (-1 == strResult.Find(L"FAILED"))
{
int index = 0;
CString strCaption = strResult.Mid(index, strResult.Find(L"|", index) - index);
index = strResult.Find(L"|", index) + 1;
CString strInformation = strResult.Mid(index, strResult.Find(L"|", index) - index);
index = strResult.Find(L"|", index) + 1;
CString session = strResult.Mid(index, strResult.GetLength() - index);
MessageBox(strInformation, strCaption, MB_OK | MB_ICONINFORMATION);
// TODO
} else {
int index = 0;
CString strCaption = strResult.Mid(index, strResult.Find(L"|", index) - index);
index = strResult.Find(L"|", index) + 1;
CString strInformation = strResult.Mid(index, strResult.GetLength() - index);
MessageBox(strInformation, strCaption, MB_OK | MB_ICONSTOP);
return;
}
這樣一個登陸功能就成功實現了!