前言
??前面實(shí)現(xiàn)了基礎(chǔ)的跳轉(zhuǎn),那么動(dòng)態(tài)交互中登錄是常用功能。
??本篇實(shí)現(xiàn)一個(gè)動(dòng)態(tài)交互的簡單登錄和注銷功能,在Qt中使用Session和Cookie技術(shù)。
Demo
??
下載地址
??鏈接:https://pan.baidu.com/s/1nkmsHgr-11Khe9k6Ntyf_g?pwd=1234
Html處理用戶輸入Session與Cookie
表單登錄submit
??Web應(yīng)用程序通常處理用戶輸入。將開發(fā)一個(gè)登錄表單,看看進(jìn)展如何。
創(chuàng)建一個(gè)名為LoginController的新類。同樣,它是從HttpRequestHandl派生的
logincontroller.h:
#ifndef LOGINCONTROLLER_H
#define LOGINCONTROLLER_H
#include "httprequesthandler.h"
using namespace stefanfrings;
class LoginController : public HttpRequestHandler {
Q_OBJECT
public:
LoginController(QObject* parent=0);
void service(HttpRequest& request, HttpResponse& response);
};
#endif // LOGINCONTROLLER_H
logincontroller.cpp:
#include "logincontroller.h"
LoginController::LoginController(QObject* parent)
:HttpRequestHandler(parent) {
// empty
}
void LoginController::service(HttpRequest &request, HttpResponse &response) {
QByteArray username=request.getParameter("username");
QByteArray password=request.getParameter("password");
qDebug("username=%s",username.constData());
qDebug("password=%s",password.constData());
response.setHeader("Content-Type", "text/html; charset=UTF-8");
response.write("<html><body>");
if (username=="test" and password=="hello") {
response.write("Yes, correct");
}
else {
response.write("<form method='POST' action='/login'>");
if (!username.isEmpty()) {
response.write("No, that was wrong!<br><br>");
}
response.write("Please log in:<br>");
response.write("Name: <input type='text' name='username'><br>");
response.write("Password: <input type='password' name='password'><br>");
response.write("<input type='submit'>");
response.write("</form");
}
response.write("</body></html>",true);
}
??(PS:html代表是提交表單)
??將這個(gè)新控制器添加到請(qǐng)求映射器中,修改requestmapper.h:
#ifndef REQUESTMAPPER_H
#define REQUESTMAPPER_H
#include "httprequesthandler.h"
#include "helloworldcontroller.h"
#include "listdatacontroller.h"
#include "logincontroller.h"
class RequestMapper : public HttpRequestHandler {
Q_OBJECT
public:
RequestMapper(QObject* parent=0);
void service(HttpRequest& request, HttpResponse& response);
private:
HelloWorldController helloWorldController;
ListDataController listDataController;
LoginController loginController;
};
#endif // REQUESTMAPPER_H
??修改requestmapper.cpp(切入了/login,調(diào)用loginController):
#include "requestmapper.h"
RequestMapper::RequestMapper(QObject* parent)
: HttpRequestHandler(parent) {
// empty
}
void RequestMapper::service(HttpRequest& request, HttpResponse& response) {
QByteArray path=request.getPath();
qDebug("RequestMapper: path=%s",path.data());
if (path=="/" || path=="/hello") {
helloWorldController.service(request, response);
}
else if (path=="/list") {
listDataController.service(request, response);
}
else if (path=="/login") {
loginController.service(request, response);
}
else {
response.setStatus(404,"Not found");
response.write("The URL is wrong, no such document.");
}
qDebug("RequestMapper: finished request");
}
??運(yùn)行程序并打開URLhttp://localhost:8080/login.將看到以下表格:
??
??嘗試使用錯(cuò)誤的名稱和密碼登錄。然后瀏覽器顯示錯(cuò)誤消息“That was wrong”,并提示重試。如果輸入了正確的憑據(jù)(用戶名“test”和密碼“hello”),則會(huì)收到成功消息。
??HTML表單定義了兩個(gè)名為“username”和“password”的輸入字段??刂破魇褂胷equest.getParameter()來獲取這些值。
??當(dāng)參數(shù)為空或傳入的HTTP請(qǐng)求中沒有這樣的參數(shù)時(shí),Request.getParameter()?返回一個(gè)空的QByteArray。后一種情況發(fā)生在打開URL時(shí)http://localhost:8080/login開始只有當(dāng)用戶單擊提交按鈕時(shí),表單字段才會(huì)從web瀏覽器發(fā)送到web服務(wù)器。
??如果需要區(qū)分空字段和缺失字段,那么可以使用request.getParameterMap(),然后檢查所需參數(shù)是否在返回的映射中。
??作為表單的替代方案,參數(shù)也可以作為URL的一部分進(jìn)行傳輸。例如,也可以通過打開URL登錄http://localhost:8080/login?username=test&password=hello.
??在URL中使用某些特殊字符時(shí),必須將其編碼為轉(zhuǎn)義序列。例如,如果用戶名是“Stefan Frings”,那么必須寫http://localhost:8080/login?username=Stefan%20Frings&password=hello.HttpRequest類會(huì)自動(dòng)將其解碼回原始形式“Stefan Frings”。
??如果需要將字符串編碼為URL格式,可以使用QUrl類。
服務(wù)器本地會(huì)話session
??(PS:session和cookie是一起搭配使用的,cookie存在本地 session可以拿到cookie來判斷是否登錄了,等一些已有的狀態(tài))
??下一個(gè)合乎邏輯的步驟是處理會(huì)話數(shù)據(jù)。這意味著,將當(dāng)前用戶的數(shù)據(jù)保存在某個(gè)地方,并在后續(xù)請(qǐng)求中使用這些數(shù)據(jù)。將存儲(chǔ)的第一個(gè)數(shù)據(jù)是用戶的姓名和登錄時(shí)間。
??QtWebApp使用隱藏的cookie來識(shí)別用戶。
??必須在控制會(huì)話存儲(chǔ)類的配置文件webapp1.ini中添加一個(gè)新的部分:
[sessions]
expirationTime=3600000
cookieName=sessionid
;cookieDomain=mydomain.com
cookiePath=/
cookieComment=Identifies the user
??過期時(shí)間定義從內(nèi)存中刪除未使用的會(huì)話后的毫秒數(shù)。當(dāng)用戶在該時(shí)間之后返回時(shí),他的會(huì)話將丟失,因此他必須再次登錄。
- expirationTime:保存時(shí)間,實(shí)際上從后面的cookie截圖可以看到是3600000ms,則是3600秒一小時(shí)的時(shí)間過期,這個(gè)保存后的默認(rèn)過期時(shí)間。
?? - sessionid:cookie名稱可以是任意名稱,但通常使用名稱“sessionid”。有些負(fù)載均衡器依賴于這個(gè)名稱,所以除非有充分的理由,否則不應(yīng)該更改它。
- cookieDomain:每個(gè)cookie總是綁定到一個(gè)域。由google.com生成的cookie只發(fā)送到該域上的服務(wù)器。如果將cookieDomain參數(shù)留空或?qū)⑵渥⑨尩?,則該參數(shù)將由web瀏覽器自動(dòng)設(shè)置??梢灾付硪粋€(gè)域名,但不知道男人為什么要這么做。所以,除非知道自己在做什么,否則就把它空著。
- cookiePath:cookie路徑可用于將cookie限制在的域的一部分。如果將cookiePath更改為/my/very/cool/online/shop,則瀏覽器將僅針對(duì)以該路徑開頭的頁面將cookie發(fā)送到的服務(wù)器。默認(rèn)值為“/”,這意味著cookie對(duì)域中的所有網(wǎng)站都有效。
- cookieComment:cookieComment是一些網(wǎng)絡(luò)瀏覽器在cookie管理屏幕中顯示的文本。
??需要HttpSessionStore類的一個(gè)實(shí)例,整個(gè)程序都可以訪問該實(shí)例,因此可以在全局空間中訪問。因此,創(chuàng)建了兩個(gè)新文件,第一個(gè)是global.h:
#ifndef GLOBAL_H
#define GLOBAL_H
#include "httpsessionstore.h"
using namespace stefanfrings;
extern HttpSessionStore* sessionStore;
#endif // GLOBAL_H
??global.cpp:
#include "global.h"
HttpSessionStore* sessionStore;
??現(xiàn)在有了一個(gè)名為“sessionStore”的全局靜態(tài)指針,整個(gè)程序可以通過包含global.h文件來訪問該指針。讓加載新的配置設(shè)置并初始化sessionStore。
??main.cpp中的更改:文章來源:http://www.zghlxwxcb.cn/news/detail-463019.html
#include "global.h"
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
QString configFileName=searchConfigFile();
// Session store
QSettings* sessionSettings=new QSettings(configFileName,QSettings::IniFormat,&app);
sessionSettings->beginGroup("sessions");
sessionStore=new HttpSessionStore(sessionSettings,&app);
// HTTP server
QSettings* listenerSettings=new QSettings(configFileName,QSettings::IniFormat,&app);
listenerSettings->beginGroup("listener");
new HttpListener(listenerSettings,new RequestMapper(&app),&app);
return app.exec();
}
??請(qǐng)注意,main.cpp現(xiàn)在加載配置文件兩次。sessionSettings對(duì)象選擇“sessions”部分,而listenerSettings選擇“l(fā)istener”部分。對(duì)于每個(gè)部分,需要一個(gè)單獨(dú)的QSettings實(shí)例,否則這些部分可能會(huì)混淆。
??既然已經(jīng)為會(huì)話數(shù)據(jù)創(chuàng)建了一個(gè)存儲(chǔ),就可以開始使用它了。添加到logincontroller.cpp:文章來源地址http://www.zghlxwxcb.cn/news/detail-463019.html
#include <QTime>
#include "logincontroller.h"
#include "global.h"
LoginController::LoginController(QObject* parent)
:HttpRequestHandler(parent) {
// empty
}
void LoginController::service(HttpRequest &request, HttpResponse &response) {
HttpSession session=sessionStore->getSession(request,response,true);
QByteArray username=request.getParameter("username");
QByteArray password=request.getParameter("password");
qDebug("username=%s",username.constData());
qDebug("password=%s",password.constData());
response.setHeader("Content-Type", "text/html; charset=UTF-8");
response.write("<html><body>");
if (session.contains("username")) {
QByteArray username=session.get("username").toByteArray();
QTime logintime=session.get("logintime").toTime();
response.write("You are already logged in.<br>");
response.write("Your name is: "+username+"<br>");
response.write("You logged in at: "+logintime.toString("HH:mm:ss")+"<br>");
}
else {
if (username=="test" and password=="hello") {
response.write("Yes, correct");
session.set("username",username);
session.set("logintime",QTime::currentTime());
}
else {
response.write("<form method='POST' action='/login'>");
if (!username.isEmpty()) {
response.write("No, that was wrong!<br><br>");
}
response.write("Please log in:<br>");
response.write("Name: <input type='text' name='username'><br>");
response.write("Password: <input type='password' name='password'><br>");
response.write("<input type='submit'>");
response.write("</form")
到了這里,關(guān)于Qt+QtWebApp開發(fā)筆記(四):http服務(wù)器使用Session和Cookie實(shí)現(xiàn)用戶密碼登錄和注銷功能的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!