pache服務(wù)器是Linux系統(tǒng)中基于提供網(wǎng)站web瀏覽的服務(wù)器,是建立web站點(diǎn)非常常用的服務(wù)器軟件之一,除了apache還有nginx。今天以apache服務(wù)器軟件為例給大家做介紹。
1、安裝apache服務(wù)程序
httpd是apache服務(wù)器軟件的軟件包名
yum安裝httpd
安裝更新完成
2、啟動(dòng)apache服務(wù),將apache服務(wù)加入到開機(jī)自啟動(dòng)中。
啟動(dòng)apache,添加開機(jī)自啟
3、打開firefox,測試127.0.0.1
地址欄中輸入127.0.0.1或localhost都可以測試!
測試本機(jī)頁面訪問,測試頁可以打開
到此為止,apache服務(wù)安裝好了,接下來我們先了解一下apache服務(wù)器配置文件和應(yīng)用服務(wù)。
服務(wù)目錄 /etc/httpd
主配置文件 /etc/httpd/conf/httpd.conf
網(wǎng)絡(luò)數(shù)據(jù)目錄 /var/www/html
訪問日志 /var/log/httpd/access_log
錯(cuò)誤日志 /var/log/httpd/error_log
apache主配置文件httpd.conf
httpd配置文件中相關(guān)選項(xiàng)的解釋:
ServerRoot /服務(wù)目錄
ServerAdmin /管理員郵箱
User /運(yùn)行服務(wù)的用戶
Group /運(yùn)行服務(wù)的用戶組
ServerName /網(wǎng)站服務(wù)的域名
DocumentRoot /網(wǎng)站數(shù)據(jù)目錄
Listen /監(jiān)聽的IP地址和端口號
Directory Index /默認(rèn)索引頁
Timeout /網(wǎng)頁超時(shí)時(shí)間
Include /需要加載的其他文件
網(wǎng)站數(shù)據(jù)目錄把網(wǎng)站數(shù)據(jù)存放在/var/www/html目錄下,叫做index.html,所以我們可以修改或替換httpd服務(wù)程序的默認(rèn)頁,操作會(huì)馬上生效的。
再次打開firefox,測試127.0.0.1
測試成功
備注:
修改網(wǎng)站數(shù)據(jù)目錄會(huì)在下一篇文章繼續(xù)給大家做介紹。
么是 CGI?
公共網(wǎng)關(guān)接口(CGI),是一套標(biāo)準(zhǔn),定義了信息是如何在 Web 服務(wù)器和客戶端腳本之間進(jìn)行交換的。
CGI 規(guī)范目前是由 NCSA 維護(hù)的,NCSA 定義 CGI 如下:
公共網(wǎng)關(guān)接口(CGI),是一種用于外部網(wǎng)關(guān)程序與信息服務(wù)器(如 HTTP 服務(wù)器)對接的接口標(biāo)準(zhǔn)。
目前的版本是 CGI/1.1,CGI/1.2 版本正在推進(jìn)中。
Web 瀏覽
為了更好地了解 CGI 的概念,讓我們點(diǎn)擊一個(gè)超鏈接,瀏覽一個(gè)特定的網(wǎng)頁或 URL,看看會(huì)發(fā)生什么。
您的瀏覽器聯(lián)系上 HTTP Web 服務(wù)器,并請求 URL,即文件名。
Web 服務(wù)器將解析 URL,并查找文件名。如果找到請求的文件,Web 服務(wù)器會(huì)把文件發(fā)送回瀏覽器,否則發(fā)送一條錯(cuò)誤消息,表明您請求了一個(gè)錯(cuò)誤的文件。
Web 瀏覽器從 Web 服務(wù)器獲取響應(yīng),并根據(jù)接收到的響應(yīng)來顯示文件或錯(cuò)誤消息。
然而,以這種方式搭建起來的 HTTP 服務(wù)器,不管何時(shí)請求目錄中的某個(gè)文件,HTTP 服務(wù)器發(fā)送回來的不是該文件,而是以程序形式執(zhí)行,并把執(zhí)行產(chǎn)生的輸出發(fā)送回瀏覽器顯示出來。
公共網(wǎng)關(guān)接口(CGI),是使得應(yīng)用程序(稱為 CGI 程序或 CGI 腳本)能夠與 Web 服務(wù)器以及客戶端進(jìn)行交互的標(biāo)準(zhǔn)協(xié)議。這些 CGI 程序可以用 Python、PERL、Shell、C 或 C++ 等進(jìn)行編寫。
CGI 架構(gòu)圖
下圖演示了 CGI 的架構(gòu):
Web 服務(wù)器配置
在您進(jìn)行 CGI 編程之前,請確保您的 Web 服務(wù)器支持 CGI,并已配置成可以處理 CGI 程序。所有由 HTTP 服務(wù)器執(zhí)行的 CGI 程序,都必須在預(yù)配置的目錄中。該目錄稱為 CGI 目錄,按照慣例命名為 /var/www/cgi-bin。雖然 CGI 文件是 C++ 可執(zhí)行文件,但是按照慣例它的擴(kuò)展名是 .cgi。
默認(rèn)情況下,Apache Web 服務(wù)器會(huì)配置在 /var/www/cgi-bin 中運(yùn)行 CGI 程序。如果您想指定其他目錄來運(yùn)行 CGI 腳本,您可以在 httpd.conf 文件中修改以下部分:
<Directory "/var/www/cgi-bin"> AllowOverride None Options ExecCGI Order allow,deny Allow from all</Directory><Directory "/var/www/cgi-bin">Options All</Directory>
在這里,我們假設(shè)已經(jīng)配置好 Web 服務(wù)器并能成功運(yùn)行,你可以運(yùn)行任意的 CGI 程序,比如 Perl 或 Shell 等。
第一個(gè) CGI 程序
請看下面的 C++ 程序:
實(shí)例
#include<iostream>usingnamespacestd; intmain(){cout << "Content-type:text/html\r\n\r\n"; cout << "<html>\n"; cout << "<head>\n"; cout << "<title>Hello World - 第一個(gè) CGI 程序</title>\n"; cout << "</head>\n"; cout << "<body>\n"; cout << "<h2>Hello World! 這是我的第一個(gè) CGI 程序</h2>\n"; cout << "</body>\n"; cout << "</html>\n"; return0;}
編譯上面的代碼,把可執(zhí)行文件命名為 cplusplus.cgi,并把這個(gè)文件保存在 /var/www/cgi-bin 目錄中。在運(yùn)行 CGI 程序之前,請使用 chmod 755 cplusplus.cgi UNIX 命令來修改文件模式,確保文件可執(zhí)行。訪問可執(zhí)行文件,您會(huì)看到下面的輸出:
Hello World! 這是我的第一個(gè) CGI 程序
上面的 C++ 程序是一個(gè)簡單的程序,把它的輸出寫在 STDOUT 文件上,即顯示在屏幕上。在這里,值得注意一點(diǎn),第一行輸出Content-type:text/html\r\n\r\n。這一行發(fā)送回瀏覽器,并指定要顯示在瀏覽器窗口上的內(nèi)容類型。您必須理解 CGI 的基本概念,這樣才能進(jìn)一步使用 Python 編寫更多復(fù)雜的 CGI 程序。C++ CGI 程序可以與任何其他外部的系統(tǒng)(如 RDBMS)進(jìn)行交互。
HTTP 頭信息
行 Content-type:text/html\r\n\r\n 是 HTTP 頭信息的組成部分,它被發(fā)送到瀏覽器,以便更好地理解頁面內(nèi)容。HTTP 頭信息的形式如下:
HTTP 字段名稱: 字段內(nèi)容例如Content-type: text/html\r\n\r\n
還有一些其他的重要的 HTTP 頭信息,這些在您的 CGI 編程中都會(huì)經(jīng)常被用到。
頭信息 | 描述 |
---|---|
Content-type: | MIME 字符串,定義返回的文件格式。例如 Content-type:text/html。 |
Expires: Date | 信息變成無效的日期。瀏覽器使用它來判斷一個(gè)頁面何時(shí)需要刷新。一個(gè)有效的日期字符串的格式應(yīng)為 01 Jan 1998 12:00:00 GMT。 |
Location: URL | 這個(gè) URL 是指應(yīng)該返回的 URL,而不是請求的 URL。你可以使用它來重定向一個(gè)請求到任意的文件。 |
Last-modified: Date | 資源的最后修改日期。 |
Content-length: N | 要返回的數(shù)據(jù)的長度,以字節(jié)為單位。瀏覽器使用這個(gè)值來表示一個(gè)文件的預(yù)計(jì)下載時(shí)間。 |
Set-Cookie: String | 通過 string 設(shè)置 cookie。 |
CGI 環(huán)境變量
所有的 CGI 程序都可以訪問下列的環(huán)境變量。這些變量在編寫 CGI 程序時(shí)扮演了非常重要的角色。
變量名 | 描述 |
---|---|
CONTENT_TYPE | 內(nèi)容的數(shù)據(jù)類型。當(dāng)客戶端向服務(wù)器發(fā)送附加內(nèi)容時(shí)使用。例如,文件上傳等功能。 |
CONTENT_LENGTH | 查詢的信息長度。只對 POST 請求可用。 |
HTTP_COOKIE | 以鍵 & 值對的形式返回設(shè)置的 cookies。 |
HTTP_USER_AGENT | 用戶代理請求標(biāo)頭字段,遞交用戶發(fā)起請求的有關(guān)信息,包含了瀏覽器的名稱、版本和其他平臺性的附加信息。 |
PATH_INFO | CGI 腳本的路徑。 |
QUERY_STRING | 通過 GET 方法發(fā)送請求時(shí)的 URL 編碼信息,包含 URL 中問號后面的參數(shù)。 |
REMOTE_ADDR | 發(fā)出請求的遠(yuǎn)程主機(jī)的 IP 地址。這在日志記錄和認(rèn)證時(shí)是非常有用的。 |
REMOTE_HOST | 發(fā)出請求的主機(jī)的完全限定名稱。如果此信息不可用,則可以用 REMOTE_ADDR 來獲取 IP 地址。 |
REQUEST_METHOD | 用于發(fā)出請求的方法。最常見的方法是 GET 和 POST。 |
SCRIPT_FILENAME | CGI 腳本的完整路徑。 |
SCRIPT_NAME | CGI 腳本的名稱。 |
SERVER_NAME | 服務(wù)器的主機(jī)名或 IP 地址。 |
SERVER_SOFTWARE | 服務(wù)器上運(yùn)行的軟件的名稱和版本。 |
下面的 CGI 程序列出了所有的 CGI 變量。
實(shí)例
#include<iostream>#include<stdlib.h>usingnamespacestd; conststringENV[24] = {"COMSPEC", "DOCUMENT_ROOT", "GATEWAY_INTERFACE", "HTTP_ACCEPT", "HTTP_ACCEPT_ENCODING", "HTTP_ACCEPT_LANGUAGE", "HTTP_CONNECTION", "HTTP_HOST", "HTTP_USER_AGENT", "PATH", "QUERY_STRING", "REMOTE_ADDR", "REMOTE_PORT", "REQUEST_METHOD", "REQUEST_URI", "SCRIPT_FILENAME", "SCRIPT_NAME", "SERVER_ADDR", "SERVER_ADMIN", "SERVER_NAME","SERVER_PORT","SERVER_PROTOCOL", "SERVER_SIGNATURE","SERVER_SOFTWARE"}; intmain(){cout << "Content-type:text/html\r\n\r\n"; cout << "<html>\n"; cout << "<head>\n"; cout << "<title>CGI 環(huán)境變量</title>\n"; cout << "</head>\n"; cout << "<body>\n"; cout << "<table border = \"0\" cellspacing = \"2\">"; for(inti = 0; i < 24; i++ ){cout << "<tr><td>" << ENV[i] << "</td><td>"; // 嘗試檢索環(huán)境變量的值char *value = getenv(ENV[i].c_str()); if(value != 0){cout << value; }else{cout << "環(huán)境變量不存在。"; }cout << "</td></tr>\n"; }cout << "</table><\n"; cout << "</body>\n"; cout << "</html>\n"; return0;}
C++ CGI 庫
在真實(shí)的實(shí)例中,您需要通過 CGI 程序執(zhí)行許多操作。這里有一個(gè)專為 C++ 程序而編寫的 CGI 庫,我們可以從ftp://ftp.gnu.org/gnu/cgicc/ 上下載這個(gè) CGI 庫,并按照下面的步驟安裝庫:
$tar xzf cgicc-X.X.X.tar.gz$cd cgicc-X.X.X/ $./configure --prefix=/usr$make$make install
您可以點(diǎn)擊 C++ CGI Lib Documentation,查看相關(guān)的庫文檔。
GET 和 POST 方法
您可能有遇到過這樣的情況,當(dāng)您需要從瀏覽器傳遞一些信息到 Web 服務(wù)器,最后再傳到 CGI 程序。通常瀏覽器會(huì)使用兩種方法把這個(gè)信息傳到 Web 服務(wù)器,分別是 GET 和 POST 方法。
使用 GET 方法傳遞信息
GET 方法發(fā)送已編碼的用戶信息追加到頁面請求中。頁面和已編碼信息通過 ? 字符分隔開,如下所示:
http://www.test.com/cgi-bin/cpp.cgi?key1=value1&key2=value2
GET 方法是默認(rèn)的從瀏覽器向 Web 服務(wù)器傳信息的方法,它會(huì)在瀏覽器的地址欄中生成一串很長的字符串。當(dāng)您向服務(wù)器傳密碼或其他一些敏感信息時(shí),不要使用 GET 方法。GET 方法有大小限制,在一個(gè)請求字符串中最多可以傳 1024 個(gè)字符。
當(dāng)使用 GET 方法時(shí),是使用 QUERY_STRING http 頭來傳遞信息,在 CGI 程序中可使用 QUERY_STRING 環(huán)境變量來訪問。
您可以通過在 URL 后跟上簡單連接的鍵值對,也可以通過使用 HTML <FORM> 標(biāo)簽的 GET 方法來傳信息。
簡單的 URL 實(shí)例:Get 方法
下面是一個(gè)簡單的 URL,使用 GET 方法傳遞兩個(gè)值給 hello_get.py 程序。
/cgi-bin/cpp_get.cgi?first_name=ZARA&last_name=ALI
下面的實(shí)例生成 cpp_get.cgi CGI 程序,用于處理 Web 瀏覽器給出的輸入。通過使用 C++ CGI 庫,可以很容易地訪問傳遞的信息:
實(shí)例
#include<iostream>#include<vector>#include<string>#include<stdio.h>#include<stdlib.h>#include<cgicc/CgiDefs.h>#include<cgicc/Cgicc.h>#include<cgicc/HTTPHTMLHeader.h>#include<cgicc/HTMLClasses.h>usingnamespacestd;usingnamespacecgicc; intmain(){CgiccformData; cout << "Content-type:text/html\r\n\r\n"; cout << "<html>\n"; cout << "<head>\n"; cout << "<title>使用 GET 和 POST 方法</title>\n"; cout << "</head>\n"; cout << "<body>\n"; form_iteratorfi = formData.getElement("first_name"); if( !fi->isEmpty() && fi != (*formData).end()){cout << "名:" << **fi << endl; }else{cout << "No text entered for first name" << endl; }cout << "<br/>\n"; fi = formData.getElement("last_name"); if( !fi->isEmpty() &&fi != (*formData).end()){cout << "姓:" << **fi << endl; }else{cout << "No text entered for last name" << endl; }cout << "<br/>\n"; cout << "</body>\n"; cout << "</html>\n"; return0;}
現(xiàn)在,編譯上面的程序,如下所示:
$g++ -o cpp_get.cgi cpp_get.cpp -lcgicc
生成 cpp_get.cgi,并把它放在 CGI 目錄中,并嘗試使用下面的鏈接進(jìn)行訪問:
/cgi-bin/cpp_get.cgi?first_name=ZARA&last_name=ALI
這會(huì)產(chǎn)生以下結(jié)果:
名:ZARA姓:ALI
簡單的表單實(shí)例:GET 方法
下面是一個(gè)簡單的實(shí)例,使用 HTML 表單和提交按鈕傳遞兩個(gè)值。我們將使用相同的 CGI 腳本 cpp_get.cgi 來處理輸入。
<formaction="/cgi-bin/cpp_get.cgi"method="get">名:<inputtype="text"name="first_name"><br/> 姓:<inputtype="text"name="last_name"/><inputtype="submit"value="提交"/></form>
下面是上述表單的實(shí)際輸出,請輸入名和姓,然后點(diǎn)擊提交按鈕查看結(jié)果。
使用 POST 方法傳遞信息
一個(gè)更可靠的向 CGI 程序傳遞信息的方法是 POST 方法。這種方法打包信息的方式與 GET 方法相同,不同的是,它不是把信息以文本字符串形式放在 URL 中的 ? 之后進(jìn)行傳遞,而是把它以單獨(dú)的消息形式進(jìn)行傳遞。該消息是以標(biāo)準(zhǔn)輸入的形式傳給 CGI 腳本的。
我們同樣使用 cpp_get.cgi 程序來處理 POST 方法。讓我們以同樣的例子,通過使用 HTML 表單和提交按鈕來傳遞兩個(gè)值,只不過這次我們使用的不是 GET 方法,而是 POST 方法,如下所示:
<formaction="/cgi-bin/cpp_get.cgi"method="post">名:<inputtype="text"name="first_name"><br/>姓:<inputtype="text"name="last_name"/><inputtype="submit"value="提交"/></form>
向 CGI 程序傳遞復(fù)選框數(shù)據(jù)
當(dāng)需要選擇多個(gè)選項(xiàng)時(shí),我們使用復(fù)選框。
下面的 HTML 代碼實(shí)例是一個(gè)帶有兩個(gè)復(fù)選框的表單:
<formaction="/cgi-bin/cpp_checkbox.cgi"method="POST"target="_blank"><inputtype="checkbox"name="maths"value="on"/> 數(shù)學(xué)<inputtype="checkbox"name="physics"value="on"/> 物理<inputtype="submit"value="選擇學(xué)科"/></form>
下面的 C++ 程序會(huì)生成 cpp_checkbox.cgi 腳本,用于處理 Web 瀏覽器通過復(fù)選框給出的輸入。
實(shí)例
#include<iostream>#include<vector>#include<string>#include<stdio.h>#include<stdlib.h>#include<cgicc/CgiDefs.h>#include<cgicc/Cgicc.h>#include<cgicc/HTTPHTMLHeader.h>#include<cgicc/HTMLClasses.h>usingnamespacestd;usingnamespacecgicc; intmain(){CgiccformData; boolmaths_flag, physics_flag; cout << "Content-type:text/html\r\n\r\n"; cout << "<html>\n"; cout << "<head>\n"; cout << "<title>向 CGI 程序傳遞復(fù)選框數(shù)據(jù)</title>\n"; cout << "</head>\n"; cout << "<body>\n"; maths_flag = formData.queryCheckbox("maths"); if(maths_flag){cout << "Maths Flag: ON " << endl; }else{cout << "Maths Flag: OFF " << endl; }cout << "<br/>\n"; physics_flag = formData.queryCheckbox("physics"); if(physics_flag){cout << "Physics Flag: ON " << endl; }else{cout << "Physics Flag: OFF " << endl; }cout << "<br/>\n"; cout << "</body>\n"; cout << "</html>\n"; return0;}
向 CGI 程序傳遞單選按鈕數(shù)據(jù)
當(dāng)只需要選擇一個(gè)選項(xiàng)時(shí),我們使用單選按鈕。
下面的 HTML 代碼實(shí)例是一個(gè)帶有兩個(gè)單選按鈕的表單:
<formaction="/cgi-bin/cpp_radiobutton.cgi"method="post"target="_blank"><inputtype="radio"name="subject"value="maths"checked="checked"/> 數(shù)學(xué) <inputtype="radio"name="subject"value="physics"/> 物理<inputtype="submit"value="選擇學(xué)科"/></form>
下面的 C++ 程序會(huì)生成 cpp_radiobutton.cgi 腳本,用于處理 Web 瀏覽器通過單選按鈕給出的輸入。
實(shí)例
#include<iostream>#include<vector>#include<string>#include<stdio.h>#include<stdlib.h>#include<cgicc/CgiDefs.h>#include<cgicc/Cgicc.h>#include<cgicc/HTTPHTMLHeader.h>#include<cgicc/HTMLClasses.h>usingnamespacestd;usingnamespacecgicc; intmain(){CgiccformData; cout << "Content-type:text/html\r\n\r\n"; cout << "<html>\n"; cout << "<head>\n"; cout << "<title>向 CGI 程序傳遞單選按鈕數(shù)據(jù)</title>\n"; cout << "</head>\n"; cout << "<body>\n"; form_iteratorfi = formData.getElement("subject"); if( !fi->isEmpty() && fi != (*formData).end()){cout << "Radio box selected: " << **fi << endl; }cout << "<br/>\n"; cout << "</body>\n"; cout << "</html>\n"; return0;}
向 CGI 程序傳遞文本區(qū)域數(shù)據(jù)
當(dāng)需要向 CGI 程序傳遞多行文本時(shí),我們使用 TEXTAREA 元素。
下面的 HTML 代碼實(shí)例是一個(gè)帶有 TEXTAREA 框的表單:
<formaction="/cgi-bin/cpp_textarea.cgi"method="post"target="_blank"><textareaname="textcontent"cols="40"rows="4">請?jiān)谶@里輸入文本...</textarea><inputtype="submit"value="提交"/></form>
下面的 C++ 程序會(huì)生成 cpp_textarea.cgi 腳本,用于處理 Web 瀏覽器通過文本區(qū)域給出的輸入。
實(shí)例
#include<iostream>#include<vector>#include<string>#include<stdio.h>#include<stdlib.h>#include<cgicc/CgiDefs.h>#include<cgicc/Cgicc.h>#include<cgicc/HTTPHTMLHeader.h>#include<cgicc/HTMLClasses.h>usingnamespacestd;usingnamespacecgicc; intmain(){CgiccformData; cout << "Content-type:text/html\r\n\r\n"; cout << "<html>\n"; cout << "<head>\n"; cout << "<title>向 CGI 程序傳遞文本區(qū)域數(shù)據(jù)</title>\n"; cout << "</head>\n"; cout << "<body>\n"; form_iteratorfi = formData.getElement("textcontent"); if( !fi->isEmpty() && fi != (*formData).end()){cout << "Text Content: " << **fi << endl; }else{cout << "No text entered" << endl; }cout << "<br/>\n"; cout << "</body>\n"; cout << "</html>\n"; return0;}
向 CGI 程序傳遞下拉框數(shù)據(jù)
當(dāng)有多個(gè)選項(xiàng)可用,但只能選擇一個(gè)或兩個(gè)選項(xiàng)時(shí),我們使用下拉框。
下面的 HTML 代碼實(shí)例是一個(gè)帶有下拉框的表單:
<formaction="/cgi-bin/cpp_dropdown.cgi"method="post"target="_blank"><selectname="dropdown"><optionvalue="Maths"selected>數(shù)學(xué)</option><optionvalue="Physics">物理</option></select><inputtype="submit"value="提交"/></form>
下面的 C++ 程序會(huì)生成 cpp_dropdown.cgi 腳本,用于處理 Web 瀏覽器通過下拉框給出的輸入。
實(shí)例
#include<iostream>#include<vector>#include<string>#include<stdio.h>#include<stdlib.h>#include<cgicc/CgiDefs.h>#include<cgicc/Cgicc.h>#include<cgicc/HTTPHTMLHeader.h>#include<cgicc/HTMLClasses.h>usingnamespacestd;usingnamespacecgicc; intmain(){CgiccformData; cout << "Content-type:text/html\r\n\r\n"; cout << "<html>\n"; cout << "<head>\n"; cout << "<title>向 CGI 程序傳遞下拉框數(shù)據(jù)</title>\n"; cout << "</head>\n"; cout << "<body>\n"; form_iteratorfi = formData.getElement("dropdown"); if( !fi->isEmpty() && fi != (*formData).end()){cout << "Value Selected: " << **fi << endl; }cout << "<br/>\n"; cout << "</body>\n"; cout << "</html>\n"; return0;}
在 CGI 中使用 Cookies
HTTP 協(xié)議是一種無狀態(tài)的協(xié)議。但對于一個(gè)商業(yè)網(wǎng)站,它需要在不同頁面間保持會(huì)話信息。例如,一個(gè)用戶在完成多個(gè)頁面的步驟之后結(jié)束注冊。但是,如何在所有網(wǎng)頁中保持用戶的會(huì)話信息。
在許多情況下,使用 cookies 是記憶和跟蹤有關(guān)用戶喜好、購買、傭金以及其他為追求更好的游客體驗(yàn)或網(wǎng)站統(tǒng)計(jì)所需信息的最有效的方法。
它是如何工作的
服務(wù)器以 cookie 的形式向訪客的瀏覽器發(fā)送一些數(shù)據(jù)。如果瀏覽器接受了 cookie,則 cookie 會(huì)以純文本記錄的形式存儲(chǔ)在訪客的硬盤上。現(xiàn)在,當(dāng)訪客訪問網(wǎng)站上的另一個(gè)頁面時(shí),會(huì)檢索 cookie。一旦找到 cookie,服務(wù)器就知道存儲(chǔ)了什么。
cookie 是一種純文本的數(shù)據(jù)記錄,帶有 5 個(gè)可變長度的字段:
Expires : cookie 的過期日期。如果此字段留空,cookie 會(huì)在訪客退出瀏覽器時(shí)過期。
Domain : 網(wǎng)站的域名。
Path : 設(shè)置 cookie 的目錄或網(wǎng)頁的路徑。如果您想從任意的目錄或網(wǎng)頁檢索 cookie,此字段可以留空。
Secure : 如果此字段包含單詞 "secure",那么 cookie 只能通過安全服務(wù)器進(jìn)行檢索。如果此字段留空,則不存在該限制。
Name=Value : cookie 以鍵值對的形式被設(shè)置和獲取。
設(shè)置 Cookies
向?yàn)g覽器發(fā)送 cookies 是非常簡單的。這些 cookies 會(huì)在 Content-type 字段之前,與 HTTP 頭一起被發(fā)送。假設(shè)您想設(shè)置 UserID 和 Password 為 cookies,設(shè)置 cookies 的步驟如下所示:
實(shí)例
#include<iostream>usingnamespacestd; intmain(){cout << "Set-Cookie:UserID=XYZ;\r\n"; cout << "Set-Cookie:Password=XYZ123;\r\n"; cout << "Set-Cookie:Domain=www.w3cschool.cc;\r\n"; cout << "Set-Cookie:Path=/perl;\n"; cout << "Content-type:text/html\r\n\r\n"; cout << "<html>\n"; cout << "<head>\n"; cout << "<title>CGI 中的 Cookies</title>\n"; cout << "</head>\n"; cout << "<body>\n"; cout << "設(shè)置 cookies" << endl; cout << "<br/>\n"; cout << "</body>\n"; cout << "</html>\n"; return0;}
從這個(gè)實(shí)例中,我們了解了如何設(shè)置 cookies。我們使用 Set-Cookie HTTP 頭來設(shè)置 cookies。
在這里,有一些設(shè)置 cookies 的屬性是可選的,比如 Expires、Domain 和 Path。值得注意的是,cookies 是在發(fā)送行"Content-type:text/html\r\n\r\n 之前被設(shè)置的。
編譯上面的程序,生成 setcookies.cgi,并嘗試使用下面的鏈接設(shè)置 cookies。它會(huì)在您的計(jì)算機(jī)上設(shè)置四個(gè) cookies:
/cgi-bin/setcookies.cgi
獲取 Cookies
檢索所有設(shè)置的 cookies 是非常簡單的。cookies 被存儲(chǔ)在 CGI 環(huán)境變量 HTTP_COOKIE 中,且它們的形式如下:
key1=value1;key2=value2;key3=value3....
下面的實(shí)例演示了如何獲取 cookies。
實(shí)例
#include<iostream>#include<vector>#include<string>#include<stdio.h>#include<stdlib.h>#include<cgicc/CgiDefs.h>#include<cgicc/Cgicc.h>#include<cgicc/HTTPHTMLHeader.h>#include<cgicc/HTMLClasses.h>usingnamespacestd;usingnamespacecgicc; intmain(){Cgicccgi; const_cookie_iteratorcci; cout << "Content-type:text/html\r\n\r\n"; cout << "<html>\n"; cout << "<head>\n"; cout << "<title>CGI 中的 Cookies</title>\n"; cout << "</head>\n"; cout << "<body>\n"; cout << "<table border = \"0\" cellspacing = \"2\">"; // 獲取環(huán)境變量constCgiEnvironment& env = cgi.getEnvironment(); for(cci = env.getCookieList().begin(); cci != env.getCookieList().end(); ++cci){cout << "<tr><td>" << cci->getName() << "</td><td>"; cout << cci->getValue(); cout << "</td></tr>\n"; }cout << "</table><\n"; cout << "<br/>\n"; cout << "</body>\n"; cout << "</html>\n"; return0;}
現(xiàn)在,編譯上面的程序,生成 getcookies.cgi,并嘗試使用下面的鏈接獲取您的計(jì)算機(jī)上所有可用的 cookies:
/cgi-bin/getcookies.cgi
這會(huì)產(chǎn)生一個(gè)列表,顯示了上一節(jié)中設(shè)置的四個(gè) cookies 以及您的計(jì)算機(jī)上所有其他的 cookies:
UserID XYZPassword XYZ123Domain www.w3cschool.ccPath /perl
文件上傳實(shí)例
為了上傳一個(gè)文件,HTML 表單必須把 enctype 屬性設(shè)置為 multipart/form-data。帶有文件類型的 input 標(biāo)簽會(huì)創(chuàng)建一個(gè) "Browse" 按鈕。
<html><body><formenctype="multipart/form-data"action="/cgi-bin/cpp_uploadfile.cgi"method="post"><p>文件:<inputtype="file"name="userfile"/></p><p><inputtype="submit"value="上傳"/></p></form></body></html>
這段代碼的結(jié)果是下面的表單:
文件:
注意:上面的實(shí)例已經(jīng)故意禁用了保存上傳的文件在我們的服務(wù)器上。您可以在自己的服務(wù)器上嘗試上面的代碼。
下面是用于處理文件上傳的腳本 cpp_uploadfile.cpp:
實(shí)例
#include<iostream>#include<vector>#include<string>#include<stdio.h>#include<stdlib.h>#include<cgicc/CgiDefs.h>#include<cgicc/Cgicc.h>#include<cgicc/HTTPHTMLHeader.h>#include<cgicc/HTMLClasses.h>usingnamespacestd;usingnamespacecgicc; intmain(){Cgicccgi; cout << "Content-type:text/html\r\n\r\n"; cout << "<html>\n"; cout << "<head>\n"; cout << "<title>CGI 中的文件上傳</title>\n"; cout << "</head>\n"; cout << "<body>\n"; // 獲取要被上傳的文件列表const_file_iteratorfile = cgi.getFile("userfile"); if(file != cgi.getFiles().end()){// 在 cout 中發(fā)送數(shù)據(jù)類型cout << HTTPContentHeader(file->getDataType()); // 在 cout 中寫入內(nèi)容file->writeToStream(cout); }cout << "<文件上傳成功>\n"; cout << "</body>\n"; cout << "</html>\n"; return0;}
上面的實(shí)例是在 cout 流中寫入內(nèi)容,但您可以打開文件流,并把上傳的文件內(nèi)容保存在目標(biāo)位置的某個(gè)文件中。
AMP 套件是一種流行的開源 Web 開發(fā)平臺,可用于運(yùn)行和部署動(dòng)態(tài)網(wǎng)站和基于 Web 的應(yīng)用程序。
? 來源:linux.cn ? 作者:Sk ? 譯者:Hacker ?
(本文字?jǐn)?shù):9231,閱讀時(shí)長大約:11 分鐘)
LAMP 套件是一種流行的開源 Web 開發(fā)平臺,可用于運(yùn)行和部署動(dòng)態(tài)網(wǎng)站和基于 Web 的應(yīng)用程序。通常,LAMP 套件由 Apache Web 服務(wù)器、MariaDB/MySQL 數(shù)據(jù)庫、PHP/Python/Perl 程序設(shè)計(jì)(腳本)語言組成。 LAMP 是 Linux,MariaDB/MYSQL,PHP/Python/Perl 的縮寫。 本教程描述了如何在 Ubuntu 18.04 LTS 服務(wù)器中安裝 Apache、MySQL、PHP(LAMP 套件)。
就本教程而言,我們將使用以下 Ubuntu 測試。
操作系統(tǒng):Ubuntu 18.04.1 LTS Server Edition
IP 地址 :192.168.225.22/24
首先,利用下面命令更新 Ubuntu 服務(wù)器:
$ sudo apt update
$ sudo apt upgrade
然后,安裝 Apache Web 服務(wù)器(命令如下):
$ sudo apt install apache2
檢查 Apache Web 服務(wù)器是否已經(jīng)運(yùn)行:
$ sudo systemctl status apache2
輸出結(jié)果大概是這樣的:
● apache2.service - The Apache HTTP Server
Loaded: loaded (/lib/systemd/system/apache2.service; enabled; vendor preset: en
Drop-In: /lib/systemd/system/apache2.service.d
└─apache2-systemd.conf
Active: active (running) since Tue 2019-02-05 10:48:03 UTC; 1min 5s ago
Main PID: 2025 (apache2)
Tasks: 55 (limit: 2320)
CGroup: /system.slice/apache2.service
├─2025 /usr/sbin/apache2 -k start
├─2027 /usr/sbin/apache2 -k start
└─2028 /usr/sbin/apache2 -k start
Feb 05 10:48:02 ubuntuserver systemd[1]: Starting The Apache HTTP Server...
Feb 05 10:48:03 ubuntuserver apachectl[2003]: AH00558: apache2: Could not reliably
Feb 05 10:48:03 ubuntuserver systemd[1]: Started The Apache HTTP Server.
祝賀你! Apache 服務(wù)已經(jīng)啟動(dòng)并運(yùn)行了!!
1.1 調(diào)整防火墻允許 Apache Web 服務(wù)器
默認(rèn)情況下,如果你已在 Ubuntu 中啟用 UFW 防火墻,則無法從遠(yuǎn)程系統(tǒng)訪問 Apache Web 服務(wù)器。 必須按照以下步驟開啟 http 和 https 端口。
首先,使用以下命令列出 Ubuntu 系統(tǒng)上可用的應(yīng)用程序配置文件:
$ sudo ufw app list
輸出結(jié)果:
Available applications:
Apache
Apache Full
Apache Secure
OpenSSH
如你所見,Apache 和 OpenSSH 應(yīng)用程序已安裝 UFW 配置文件。你可以使用 ufw app info "Profile Name" 命令列出有關(guān)每個(gè)配置文件及其包含的規(guī)則的信息。
讓我們研究一下 “Apache Full” 配置文件。 為此,請運(yùn)行:
$ sudo ufw app info "Apache Full"
輸出結(jié)果:
Profile: Apache Full
Title: Web Server (HTTP,HTTPS)
Description: Apache v2 is the next generation of the omnipresent Apache web
server.
Ports:
80,443/tcp
如你所見,“Apache Full” 配置文件包含了啟用經(jīng)由端口 80 和 443 的傳輸規(guī)則:
現(xiàn)在,運(yùn)行以下命令配置允許 HTTP 和 HTTPS 傳入通信:
$ sudo ufw allow in "Apache Full"
Rules updated
Rules updated (v6)
如果你不想允許 HTTP 通信,而只允許 HTTP(80) 通信,請運(yùn)行:
$ sudo ufw app info "Apache"
1.2 測試 Apache Web 服務(wù)器
現(xiàn)在,打開 Web 瀏覽器并導(dǎo)航到 http://localhost/ 或 http://IP-Address/ 來訪問 Apache 測試頁。
如果看到上面類似的顯示內(nèi)容,那就成功了。 Apache 服務(wù)器正在工作!
在 Ubuntu 安裝 MySQL 請運(yùn)行:
$ sudo apt install mysql-server
使用以下命令驗(yàn)證 MySQL 服務(wù)是否正在運(yùn)行:
$ sudo systemctl status mysql
輸出結(jié)果:
● mysql.service - MySQL Community Server
Loaded: loaded (/lib/systemd/system/mysql.service; enabled; vendor preset: enab
Active: active (running) since Tue 2019-02-05 11:07:50 UTC; 17s ago
Main PID: 3423 (mysqld)
Tasks: 27 (limit: 2320)
CGroup: /system.slice/mysql.service
└─3423 /usr/sbin/mysqld --daemonize --pid-file=/run/mysqld/mysqld.pid
Feb 05 11:07:49 ubuntuserver systemd[1]: Starting MySQL Community Server...
Feb 05 11:07:50 ubuntuserver systemd[1]: Started MySQL Community Server.
MySQL 正在運(yùn)行!
2.1 配置數(shù)據(jù)庫管理用戶(root)密碼
默認(rèn)情況下,MySQL root 用戶密碼為空。你需要通過運(yùn)行以下腳本使你的 MySQL 服務(wù)器安全:
$ sudo mysql_secure_installation
系統(tǒng)將詢問你是否要安裝 “VALIDATE PASSWORD plugin(密碼驗(yàn)證插件)”。該插件允許用戶為數(shù)據(jù)庫配置強(qiáng)密碼憑據(jù)。如果啟用,它將自動(dòng)檢查密碼的強(qiáng)度并強(qiáng)制用戶設(shè)置足夠安全的密碼。禁用此插件是安全的。但是,必須為數(shù)據(jù)庫使用唯一的強(qiáng)密碼憑據(jù)。如果不想啟用此插件,只需按任意鍵即可跳過密碼驗(yàn)證部分,然后繼續(xù)其余步驟。
如果回答是 y,則會(huì)要求你選擇密碼驗(yàn)證級別。
Securing the MySQL server deployment.
Connecting to MySQL using a blank password.
VALIDATE PASSWORD PLUGIN can be used to test passwords
and improve security. It checks the strength of password
and allows the users to set only those passwords which are
secure enough. Would you like to setup VALIDATE PASSWORD plugin?
Press y|Y for Yes, any other key for No y
可用的密碼驗(yàn)證有 “l(fā)ow(低)”、 “medium(中)” 和 “strong(強(qiáng))”。只需輸入適當(dāng)?shù)臄?shù)字(0 表示低,1 表示中,2 表示強(qiáng)密碼)并按回車鍵。
There are three levels of password validation policy:
LOW Length >= 8
MEDIUM Length >= 8, numeric, mixed case, and special characters
STRONG Length >= 8, numeric, mixed case, special characters and dictionary file
Please enter 0 = LOW, 1 = MEDIUM and 2 = STRONG:
現(xiàn)在,輸入 MySQL root 用戶的密碼。請注意,必須根據(jù)上一步中選擇的密碼策略,為 MySQL root 用戶使用密碼。如果你未啟用該插件,則只需使用你選擇的任意強(qiáng)度且唯一的密碼即可。
Please set the password for root here.
New password:
Re-enter new password:
Estimated strength of the password: 50
Do you wish to continue with the password provided?(Press y|Y for Yes, any other key for No) : y
兩次輸入密碼后,你將看到密碼強(qiáng)度(在此示例情況下為 50)。如果你確定可以,請按 y 繼續(xù)提供的密碼。如果對密碼長度不滿意,請按其他任意鍵并設(shè)置一個(gè)強(qiáng)密碼。我現(xiàn)在的密碼可以,所以我選擇了y。
對于其余的問題,只需鍵入 y 并按回車鍵。這將刪除匿名用戶、禁止 root 用戶遠(yuǎn)程登錄并刪除 test(測試)數(shù)據(jù)庫。
Remove anonymous users? (Press y|Y for Yes, any other key for No) : y
Success.
Normally, root should only be allowed to connect from
'localhost'. This ensures that someone cannot guess at
the root password from the network.
Disallow root login remotely? (Press y|Y for Yes, any other key for No) : y
Success.
By default, MySQL comes with a database named 'test' that
anyone can access. This is also intended only for testing,
and should be removed before moving into a production
environment.
Remove test database and access to it? (Press y|Y for Yes, any other key for No) : y
- Dropping test database...
Success.
- Removing privileges on test database...
Success.
Reloading the privilege tables will ensure that all changes
made so far will take effect immediately.
Reload privilege tables now? (Press y|Y for Yes, any other key for No) : y
Success.
All done!
以上就是為 MySQL root 用戶設(shè)置密碼。
2.2 更改 MySQL 超級用戶的身份驗(yàn)證方法
默認(rèn)情況下,Ubuntu 系統(tǒng)的 MySQL root 用戶為 MySQL 5.7 版本及更新的版本使用插件 auth_socket 設(shè)置身份驗(yàn)證。盡管它增強(qiáng)了安全性,但是當(dāng)你使用任何外部程序(例如 phpMyAdmin)訪問數(shù)據(jù)庫服務(wù)器時(shí),也會(huì)變得更困難。要解決此問題,你需要將身份驗(yàn)證方法從 auth_socket 更改為 mysql_native_password。為此,請使用以下命令登錄到你的 MySQL 提示符下:
$ sudo mysql
在 MySQL 提示符下運(yùn)行以下命令,找到所有 MySQL 當(dāng)前用戶帳戶的身份驗(yàn)證方法:
SELECT user,authentication_string,plugin,host FROM mysql.user;
輸出結(jié)果:
+------------------|-------------------------------------------|-----------------------|-----------+
| user | authentication_string | plugin | host |
+------------------|-------------------------------------------|-----------------------|-----------+
| root | | auth_socket | localhost |
| mysql.session | *THISISNOTAVALIDPASSWORDTHATCANBEUSEDHERE | mysql_native_password | localhost |
| mysql.sys | *THISISNOTAVALIDPASSWORDTHATCANBEUSEDHERE | mysql_native_password | localhost |
| debian-sys-maint | *F126737722832701DD3979741508F05FA71E5BA0 | mysql_native_password | localhost |
+------------------|-------------------------------------------|-----------------------|-----------+
4 rows in set (0.00 sec)
如你所見,Mysql root 用戶使用 auth_socket 插件進(jìn)行身份驗(yàn)證。
要將此身份驗(yàn)證更改為 mysql_native_password 方法,請?jiān)?MySQL 提示符下運(yùn)行以下命令。 別忘了用你選擇的強(qiáng)大唯一的密碼替換 password。 如果已啟用 VALIDATION 插件,請確保已根據(jù)當(dāng)前策略要求使用了強(qiáng)密碼。
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'password';
使用以下命令更新數(shù)據(jù)庫:
FLUSH PRIVILEGES;
使用命令再次檢查身份驗(yàn)證方法是否已更改:
SELECT user,authentication_string,plugin,host FROM mysql.user;
輸出結(jié)果:
好!MySQL root 用戶就可以使用密碼進(jìn)行身份驗(yàn)證來訪問 mysql shell。
從 MySQL 提示符下退出:
exit
安裝 PHP 請運(yùn)行:
$ sudo apt install php libapache2-mod-php php-mysql
安裝 PHP 后,在 Apache 文檔根目錄中創(chuàng)建 info.php 文件。通常,在大多數(shù)基于 Debian 的 Linux 發(fā)行版中,Apache 文檔根目錄為 /var/www/html/ 或 /var/www/。Ubuntu 18.04 LTS 系統(tǒng)下,文檔根目錄是 /var/www/html/。
在 Apache 根目錄中創(chuàng)建 info.php 文件:
$ sudo vi /var/www/html/info.php
在此文件中編輯如下內(nèi)容:
<?php
phpinfo();
?>
然后按下 ESC 鍵并且輸入 :wq 保存并退出此文件。重新啟動(dòng) Apache 服務(wù)使更改生效。
$ sudo systemctl restart apache2
3.1 測試 PHP
打開 Web 瀏覽器,然后導(dǎo)航到 URL http://IP地址/info.php 。
你就將看到 PHP 測試頁面。
通常,當(dāng)用戶向 Web 服務(wù)器發(fā)出請求時(shí),Apache 首先會(huì)在文檔根目錄中查找名為 index.html 的文件。如果你想將 Apache 更改為 php 文件提供服務(wù)而不是其他文件,請將 dir.conf 配置文件中的 index.php 移至第一個(gè)位置,如下所示:
$ sudo vi /etc/apache2/mods-enabled/dir.conf
上面的配置文件(dir.conf) 內(nèi)容如下:
<IfModule mod_dir.c>
DirectoryIndex index.html index.cgi index.pl index.php index.xhtml index.htm
</IfModule>
# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
將 index.php 移動(dòng)到最前面。更改后,dir.conf 文件內(nèi)容看起來如下所示。
<IfModule mod_dir.c>
DirectoryIndex index.php index.html index.cgi index.pl index.xhtml index.htm
</IfModule>
# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
然后按下 ESC 鍵并且輸入 :wq 保存并關(guān)閉此文件。重新啟動(dòng) Apache 服務(wù)使更改生效。
$ sudo systemctl restart apache2
3.2 安裝 PHP 模塊
為了增加 PHP 的功能,可以安裝一些其他的 PHP 模塊。
要列出可用的 PHP 模塊,請運(yùn)行:
$ sudo apt-cache search php- | less
輸出結(jié)果:
使用方向鍵瀏覽結(jié)果。要退出,請輸入 q 并按下回車鍵。
要查找任意 php 模塊的詳細(xì)信息,例如 php-gd,請運(yùn)行:
$ sudo apt-cache show php-gd
安裝 PHP 模塊請運(yùn)行:
$ sudo apt install php-gd
安裝所有的模塊(雖然沒有必要),請運(yùn)行:
$ sudo apt-get install php*
安裝任何 php 模塊后,請不要忘記重新啟動(dòng) Apache 服務(wù)。要檢查模塊是否已加載,請?jiān)跒g覽器中打開 info.php 文件并檢查是否存在。
接下來,你可能需要安裝數(shù)據(jù)庫管理工具,以通過 Web 瀏覽器輕松管理數(shù)據(jù)庫。如果是這樣,請按照以下鏈接中的說明安裝 phpMyAdmin。
祝賀你!我們已經(jīng)在 Ubuntu 服務(wù)器中成功配置了 LAMP 套件。
via: www.ostechnix.com
作者: SK 選題: lujun9972 譯者: stevenzdg988 校對: wxy
本文由 LCTT 原創(chuàng)編譯, Linux中國 榮譽(yù)推出
*請認(rèn)真填寫需求信息,我們會(huì)在24小時(shí)內(nèi)與您取得聯(lián)系。