pache服务器是Linux系统中基于提供网站web浏览的服务器,是建立web站点非常常用的服务器软件之一,除了apache还有nginx。今天以apache服务器软件为例给大家做介绍。
1、安装apache服务程序
httpd是apache服务器软件的软件包名
yum安装httpd
安装更新完成
2、启动apache服务,将apache服务加入到开机自启动中。
启动apache,添加开机自启
3、打开firefox,测试127.0.0.1
地址栏中输入127.0.0.1或localhost都可以测试!
测试本机页面访问,测试页可以打开
到此为止,apache服务安装好了,接下来我们先了解一下apache服务器配置文件和应用服务。
服务目录 /etc/httpd
主配置文件 /etc/httpd/conf/httpd.conf
网络数据目录 /var/www/html
访问日志 /var/log/httpd/access_log
错误日志 /var/log/httpd/error_log
apache主配置文件httpd.conf
httpd配置文件中相关选项的解释:
ServerRoot /服务目录
ServerAdmin /管理员邮箱
User /运行服务的用户
Group /运行服务的用户组
ServerName /网站服务的域名
DocumentRoot /网站数据目录
Listen /监听的IP地址和端口号
Directory Index /默认索引页
Timeout /网页超时时间
Include /需要加载的其他文件
网站数据目录把网站数据存放在/var/www/html目录下,叫做index.html,所以我们可以修改或替换httpd服务程序的默认页,操作会马上生效的。
再次打开firefox,测试127.0.0.1
测试成功
备注:
修改网站数据目录会在下一篇文章继续给大家做介绍。
么是 CGI?
公共网关接口(CGI),是一套标准,定义了信息是如何在 Web 服务器和客户端脚本之间进行交换的。
CGI 规范目前是由 NCSA 维护的,NCSA 定义 CGI 如下:
公共网关接口(CGI),是一种用于外部网关程序与信息服务器(如 HTTP 服务器)对接的接口标准。
目前的版本是 CGI/1.1,CGI/1.2 版本正在推进中。
Web 浏览
为了更好地了解 CGI 的概念,让我们点击一个超链接,浏览一个特定的网页或 URL,看看会发生什么。
您的浏览器联系上 HTTP Web 服务器,并请求 URL,即文件名。
Web 服务器将解析 URL,并查找文件名。如果找到请求的文件,Web 服务器会把文件发送回浏览器,否则发送一条错误消息,表明您请求了一个错误的文件。
Web 浏览器从 Web 服务器获取响应,并根据接收到的响应来显示文件或错误消息。
然而,以这种方式搭建起来的 HTTP 服务器,不管何时请求目录中的某个文件,HTTP 服务器发送回来的不是该文件,而是以程序形式执行,并把执行产生的输出发送回浏览器显示出来。
公共网关接口(CGI),是使得应用程序(称为 CGI 程序或 CGI 脚本)能够与 Web 服务器以及客户端进行交互的标准协议。这些 CGI 程序可以用 Python、PERL、Shell、C 或 C++ 等进行编写。
CGI 架构图
下图演示了 CGI 的架构:
Web 服务器配置
在您进行 CGI 编程之前,请确保您的 Web 服务器支持 CGI,并已配置成可以处理 CGI 程序。所有由 HTTP 服务器执行的 CGI 程序,都必须在预配置的目录中。该目录称为 CGI 目录,按照惯例命名为 /var/www/cgi-bin。虽然 CGI 文件是 C++ 可执行文件,但是按照惯例它的扩展名是 .cgi。
默认情况下,Apache Web 服务器会配置在 /var/www/cgi-bin 中运行 CGI 程序。如果您想指定其他目录来运行 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>
在这里,我们假设已经配置好 Web 服务器并能成功运行,你可以运行任意的 CGI 程序,比如 Perl 或 Shell 等。
第一个 CGI 程序
请看下面的 C++ 程序:
实例
#include<iostream>usingnamespacestd; intmain(){cout << "Content-type:text/html\r\n\r\n"; cout << "<html>\n"; cout << "<head>\n"; cout << "<title>Hello World - 第一个 CGI 程序</title>\n"; cout << "</head>\n"; cout << "<body>\n"; cout << "<h2>Hello World! 这是我的第一个 CGI 程序</h2>\n"; cout << "</body>\n"; cout << "</html>\n"; return0;}
编译上面的代码,把可执行文件命名为 cplusplus.cgi,并把这个文件保存在 /var/www/cgi-bin 目录中。在运行 CGI 程序之前,请使用 chmod 755 cplusplus.cgi UNIX 命令来修改文件模式,确保文件可执行。访问可执行文件,您会看到下面的输出:
Hello World! 这是我的第一个 CGI 程序
上面的 C++ 程序是一个简单的程序,把它的输出写在 STDOUT 文件上,即显示在屏幕上。在这里,值得注意一点,第一行输出Content-type:text/html\r\n\r\n。这一行发送回浏览器,并指定要显示在浏览器窗口上的内容类型。您必须理解 CGI 的基本概念,这样才能进一步使用 Python 编写更多复杂的 CGI 程序。C++ CGI 程序可以与任何其他外部的系统(如 RDBMS)进行交互。
HTTP 头信息
行 Content-type:text/html\r\n\r\n 是 HTTP 头信息的组成部分,它被发送到浏览器,以便更好地理解页面内容。HTTP 头信息的形式如下:
HTTP 字段名称: 字段内容例如Content-type: text/html\r\n\r\n
还有一些其他的重要的 HTTP 头信息,这些在您的 CGI 编程中都会经常被用到。
头信息 | 描述 |
---|---|
Content-type: | MIME 字符串,定义返回的文件格式。例如 Content-type:text/html。 |
Expires: Date | 信息变成无效的日期。浏览器使用它来判断一个页面何时需要刷新。一个有效的日期字符串的格式应为 01 Jan 1998 12:00:00 GMT。 |
Location: URL | 这个 URL 是指应该返回的 URL,而不是请求的 URL。你可以使用它来重定向一个请求到任意的文件。 |
Last-modified: Date | 资源的最后修改日期。 |
Content-length: N | 要返回的数据的长度,以字节为单位。浏览器使用这个值来表示一个文件的预计下载时间。 |
Set-Cookie: String | 通过 string 设置 cookie。 |
CGI 环境变量
所有的 CGI 程序都可以访问下列的环境变量。这些变量在编写 CGI 程序时扮演了非常重要的角色。
变量名 | 描述 |
---|---|
CONTENT_TYPE | 内容的数据类型。当客户端向服务器发送附加内容时使用。例如,文件上传等功能。 |
CONTENT_LENGTH | 查询的信息长度。只对 POST 请求可用。 |
HTTP_COOKIE | 以键 & 值对的形式返回设置的 cookies。 |
HTTP_USER_AGENT | 用户代理请求标头字段,递交用户发起请求的有关信息,包含了浏览器的名称、版本和其他平台性的附加信息。 |
PATH_INFO | CGI 脚本的路径。 |
QUERY_STRING | 通过 GET 方法发送请求时的 URL 编码信息,包含 URL 中问号后面的参数。 |
REMOTE_ADDR | 发出请求的远程主机的 IP 地址。这在日志记录和认证时是非常有用的。 |
REMOTE_HOST | 发出请求的主机的完全限定名称。如果此信息不可用,则可以用 REMOTE_ADDR 来获取 IP 地址。 |
REQUEST_METHOD | 用于发出请求的方法。最常见的方法是 GET 和 POST。 |
SCRIPT_FILENAME | CGI 脚本的完整路径。 |
SCRIPT_NAME | CGI 脚本的名称。 |
SERVER_NAME | 服务器的主机名或 IP 地址。 |
SERVER_SOFTWARE | 服务器上运行的软件的名称和版本。 |
下面的 CGI 程序列出了所有的 CGI 变量。
实例
#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 环境变量</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>"; // 尝试检索环境变量的值char *value = getenv(ENV[i].c_str()); if(value != 0){cout << value; }else{cout << "环境变量不存在。"; }cout << "</td></tr>\n"; }cout << "</table><\n"; cout << "</body>\n"; cout << "</html>\n"; return0;}
C++ CGI 库
在真实的实例中,您需要通过 CGI 程序执行许多操作。这里有一个专为 C++ 程序而编写的 CGI 库,我们可以从ftp://ftp.gnu.org/gnu/cgicc/ 上下载这个 CGI 库,并按照下面的步骤安装库:
$tar xzf cgicc-X.X.X.tar.gz$cd cgicc-X.X.X/ $./configure --prefix=/usr$make$make install
您可以点击 C++ CGI Lib Documentation,查看相关的库文档。
GET 和 POST 方法
您可能有遇到过这样的情况,当您需要从浏览器传递一些信息到 Web 服务器,最后再传到 CGI 程序。通常浏览器会使用两种方法把这个信息传到 Web 服务器,分别是 GET 和 POST 方法。
使用 GET 方法传递信息
GET 方法发送已编码的用户信息追加到页面请求中。页面和已编码信息通过 ? 字符分隔开,如下所示:
http://www.test.com/cgi-bin/cpp.cgi?key1=value1&key2=value2
GET 方法是默认的从浏览器向 Web 服务器传信息的方法,它会在浏览器的地址栏中生成一串很长的字符串。当您向服务器传密码或其他一些敏感信息时,不要使用 GET 方法。GET 方法有大小限制,在一个请求字符串中最多可以传 1024 个字符。
当使用 GET 方法时,是使用 QUERY_STRING http 头来传递信息,在 CGI 程序中可使用 QUERY_STRING 环境变量来访问。
您可以通过在 URL 后跟上简单连接的键值对,也可以通过使用 HTML <FORM> 标签的 GET 方法来传信息。
简单的 URL 实例:Get 方法
下面是一个简单的 URL,使用 GET 方法传递两个值给 hello_get.py 程序。
/cgi-bin/cpp_get.cgi?first_name=ZARA&last_name=ALI
下面的实例生成 cpp_get.cgi CGI 程序,用于处理 Web 浏览器给出的输入。通过使用 C++ CGI 库,可以很容易地访问传递的信息:
实例
#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;}
现在,编译上面的程序,如下所示:
$g++ -o cpp_get.cgi cpp_get.cpp -lcgicc
生成 cpp_get.cgi,并把它放在 CGI 目录中,并尝试使用下面的链接进行访问:
/cgi-bin/cpp_get.cgi?first_name=ZARA&last_name=ALI
这会产生以下结果:
名:ZARA姓:ALI
简单的表单实例:GET 方法
下面是一个简单的实例,使用 HTML 表单和提交按钮传递两个值。我们将使用相同的 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>
下面是上述表单的实际输出,请输入名和姓,然后点击提交按钮查看结果。
使用 POST 方法传递信息
一个更可靠的向 CGI 程序传递信息的方法是 POST 方法。这种方法打包信息的方式与 GET 方法相同,不同的是,它不是把信息以文本字符串形式放在 URL 中的 ? 之后进行传递,而是把它以单独的消息形式进行传递。该消息是以标准输入的形式传给 CGI 脚本的。
我们同样使用 cpp_get.cgi 程序来处理 POST 方法。让我们以同样的例子,通过使用 HTML 表单和提交按钮来传递两个值,只不过这次我们使用的不是 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 程序传递复选框数据
当需要选择多个选项时,我们使用复选框。
下面的 HTML 代码实例是一个带有两个复选框的表单:
<formaction="/cgi-bin/cpp_checkbox.cgi"method="POST"target="_blank"><inputtype="checkbox"name="maths"value="on"/> 数学<inputtype="checkbox"name="physics"value="on"/> 物理<inputtype="submit"value="选择学科"/></form>
下面的 C++ 程序会生成 cpp_checkbox.cgi 脚本,用于处理 Web 浏览器通过复选框给出的输入。
实例
#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 程序传递复选框数据</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 程序传递单选按钮数据
当只需要选择一个选项时,我们使用单选按钮。
下面的 HTML 代码实例是一个带有两个单选按钮的表单:
<formaction="/cgi-bin/cpp_radiobutton.cgi"method="post"target="_blank"><inputtype="radio"name="subject"value="maths"checked="checked"/> 数学 <inputtype="radio"name="subject"value="physics"/> 物理<inputtype="submit"value="选择学科"/></form>
下面的 C++ 程序会生成 cpp_radiobutton.cgi 脚本,用于处理 Web 浏览器通过单选按钮给出的输入。
实例
#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 程序传递单选按钮数据</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 程序传递文本区域数据
当需要向 CGI 程序传递多行文本时,我们使用 TEXTAREA 元素。
下面的 HTML 代码实例是一个带有 TEXTAREA 框的表单:
<formaction="/cgi-bin/cpp_textarea.cgi"method="post"target="_blank"><textareaname="textcontent"cols="40"rows="4">请在这里输入文本...</textarea><inputtype="submit"value="提交"/></form>
下面的 C++ 程序会生成 cpp_textarea.cgi 脚本,用于处理 Web 浏览器通过文本区域给出的输入。
实例
#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 程序传递文本区域数据</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 程序传递下拉框数据
当有多个选项可用,但只能选择一个或两个选项时,我们使用下拉框。
下面的 HTML 代码实例是一个带有下拉框的表单:
<formaction="/cgi-bin/cpp_dropdown.cgi"method="post"target="_blank"><selectname="dropdown"><optionvalue="Maths"selected>数学</option><optionvalue="Physics">物理</option></select><inputtype="submit"value="提交"/></form>
下面的 C++ 程序会生成 cpp_dropdown.cgi 脚本,用于处理 Web 浏览器通过下拉框给出的输入。
实例
#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 程序传递下拉框数据</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 协议是一种无状态的协议。但对于一个商业网站,它需要在不同页面间保持会话信息。例如,一个用户在完成多个页面的步骤之后结束注册。但是,如何在所有网页中保持用户的会话信息。
在许多情况下,使用 cookies 是记忆和跟踪有关用户喜好、购买、佣金以及其他为追求更好的游客体验或网站统计所需信息的最有效的方法。
它是如何工作的
服务器以 cookie 的形式向访客的浏览器发送一些数据。如果浏览器接受了 cookie,则 cookie 会以纯文本记录的形式存储在访客的硬盘上。现在,当访客访问网站上的另一个页面时,会检索 cookie。一旦找到 cookie,服务器就知道存储了什么。
cookie 是一种纯文本的数据记录,带有 5 个可变长度的字段:
Expires : cookie 的过期日期。如果此字段留空,cookie 会在访客退出浏览器时过期。
Domain : 网站的域名。
Path : 设置 cookie 的目录或网页的路径。如果您想从任意的目录或网页检索 cookie,此字段可以留空。
Secure : 如果此字段包含单词 "secure",那么 cookie 只能通过安全服务器进行检索。如果此字段留空,则不存在该限制。
Name=Value : cookie 以键值对的形式被设置和获取。
设置 Cookies
向浏览器发送 cookies 是非常简单的。这些 cookies 会在 Content-type 字段之前,与 HTTP 头一起被发送。假设您想设置 UserID 和 Password 为 cookies,设置 cookies 的步骤如下所示:
实例
#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 << "设置 cookies" << endl; cout << "<br/>\n"; cout << "</body>\n"; cout << "</html>\n"; return0;}
从这个实例中,我们了解了如何设置 cookies。我们使用 Set-Cookie HTTP 头来设置 cookies。
在这里,有一些设置 cookies 的属性是可选的,比如 Expires、Domain 和 Path。值得注意的是,cookies 是在发送行"Content-type:text/html\r\n\r\n 之前被设置的。
编译上面的程序,生成 setcookies.cgi,并尝试使用下面的链接设置 cookies。它会在您的计算机上设置四个 cookies:
/cgi-bin/setcookies.cgi
获取 Cookies
检索所有设置的 cookies 是非常简单的。cookies 被存储在 CGI 环境变量 HTTP_COOKIE 中,且它们的形式如下:
key1=value1;key2=value2;key3=value3....
下面的实例演示了如何获取 cookies。
实例
#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\">"; // 获取环境变量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;}
现在,编译上面的程序,生成 getcookies.cgi,并尝试使用下面的链接获取您的计算机上所有可用的 cookies:
/cgi-bin/getcookies.cgi
这会产生一个列表,显示了上一节中设置的四个 cookies 以及您的计算机上所有其他的 cookies:
UserID XYZPassword XYZ123Domain www.w3cschool.ccPath /perl
文件上传实例
为了上传一个文件,HTML 表单必须把 enctype 属性设置为 multipart/form-data。带有文件类型的 input 标签会创建一个 "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>
这段代码的结果是下面的表单:
文件:
注意:上面的实例已经故意禁用了保存上传的文件在我们的服务器上。您可以在自己的服务器上尝试上面的代码。
下面是用于处理文件上传的脚本 cpp_uploadfile.cpp:
实例
#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 中发送数据类型cout << HTTPContentHeader(file->getDataType()); // 在 cout 中写入内容file->writeToStream(cout); }cout << "<文件上传成功>\n"; cout << "</body>\n"; cout << "</html>\n"; return0;}
上面的实例是在 cout 流中写入内容,但您可以打开文件流,并把上传的文件内容保存在目标位置的某个文件中。
AMP 套件是一种流行的开源 Web 开发平台,可用于运行和部署动态网站和基于 Web 的应用程序。
• 来源:linux.cn • 作者:Sk • 译者:Hacker •
(本文字数:9231,阅读时长大约:11 分钟)
LAMP 套件是一种流行的开源 Web 开发平台,可用于运行和部署动态网站和基于 Web 的应用程序。通常,LAMP 套件由 Apache Web 服务器、MariaDB/MySQL 数据库、PHP/Python/Perl 程序设计(脚本)语言组成。 LAMP 是 Linux,MariaDB/MYSQL,PHP/Python/Perl 的缩写。 本教程描述了如何在 Ubuntu 18.04 LTS 服务器中安装 Apache、MySQL、PHP(LAMP 套件)。
就本教程而言,我们将使用以下 Ubuntu 测试。
操作系统:Ubuntu 18.04.1 LTS Server Edition
IP 地址 :192.168.225.22/24
首先,利用下面命令更新 Ubuntu 服务器:
$ sudo apt update
$ sudo apt upgrade
然后,安装 Apache Web 服务器(命令如下):
$ sudo apt install apache2
检查 Apache Web 服务器是否已经运行:
$ sudo systemctl status apache2
输出结果大概是这样的:
● 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 服务已经启动并运行了!!
1.1 调整防火墙允许 Apache Web 服务器
默认情况下,如果你已在 Ubuntu 中启用 UFW 防火墙,则无法从远程系统访问 Apache Web 服务器。 必须按照以下步骤开启 http 和 https 端口。
首先,使用以下命令列出 Ubuntu 系统上可用的应用程序配置文件:
$ sudo ufw app list
输出结果:
Available applications:
Apache
Apache Full
Apache Secure
OpenSSH
如你所见,Apache 和 OpenSSH 应用程序已安装 UFW 配置文件。你可以使用 ufw app info "Profile Name" 命令列出有关每个配置文件及其包含的规则的信息。
让我们研究一下 “Apache Full” 配置文件。 为此,请运行:
$ sudo ufw app info "Apache Full"
输出结果:
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” 配置文件包含了启用经由端口 80 和 443 的传输规则:
现在,运行以下命令配置允许 HTTP 和 HTTPS 传入通信:
$ sudo ufw allow in "Apache Full"
Rules updated
Rules updated (v6)
如果你不想允许 HTTP 通信,而只允许 HTTP(80) 通信,请运行:
$ sudo ufw app info "Apache"
1.2 测试 Apache Web 服务器
现在,打开 Web 浏览器并导航到 http://localhost/ 或 http://IP-Address/ 来访问 Apache 测试页。
如果看到上面类似的显示内容,那就成功了。 Apache 服务器正在工作!
在 Ubuntu 安装 MySQL 请运行:
$ sudo apt install mysql-server
使用以下命令验证 MySQL 服务是否正在运行:
$ sudo systemctl status mysql
输出结果:
● 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 正在运行!
2.1 配置数据库管理用户(root)密码
默认情况下,MySQL root 用户密码为空。你需要通过运行以下脚本使你的 MySQL 服务器安全:
$ sudo mysql_secure_installation
系统将询问你是否要安装 “VALIDATE PASSWORD plugin(密码验证插件)”。该插件允许用户为数据库配置强密码凭据。如果启用,它将自动检查密码的强度并强制用户设置足够安全的密码。禁用此插件是安全的。但是,必须为数据库使用唯一的强密码凭据。如果不想启用此插件,只需按任意键即可跳过密码验证部分,然后继续其余步骤。
如果回答是 y,则会要求你选择密码验证级别。
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
可用的密码验证有 “low(低)”、 “medium(中)” 和 “strong(强)”。只需输入适当的数字(0 表示低,1 表示中,2 表示强密码)并按回车键。
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:
现在,输入 MySQL root 用户的密码。请注意,必须根据上一步中选择的密码策略,为 MySQL root 用户使用密码。如果你未启用该插件,则只需使用你选择的任意强度且唯一的密码即可。
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
两次输入密码后,你将看到密码强度(在此示例情况下为 50)。如果你确定可以,请按 y 继续提供的密码。如果对密码长度不满意,请按其他任意键并设置一个强密码。我现在的密码可以,所以我选择了y。
对于其余的问题,只需键入 y 并按回车键。这将删除匿名用户、禁止 root 用户远程登录并删除 test(测试)数据库。
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 用户设置密码。
2.2 更改 MySQL 超级用户的身份验证方法
默认情况下,Ubuntu 系统的 MySQL root 用户为 MySQL 5.7 版本及更新的版本使用插件 auth_socket 设置身份验证。尽管它增强了安全性,但是当你使用任何外部程序(例如 phpMyAdmin)访问数据库服务器时,也会变得更困难。要解决此问题,你需要将身份验证方法从 auth_socket 更改为 mysql_native_password。为此,请使用以下命令登录到你的 MySQL 提示符下:
$ sudo mysql
在 MySQL 提示符下运行以下命令,找到所有 MySQL 当前用户帐户的身份验证方法:
SELECT user,authentication_string,plugin,host FROM mysql.user;
输出结果:
+------------------|-------------------------------------------|-----------------------|-----------+
| 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 插件进行身份验证。
要将此身份验证更改为 mysql_native_password 方法,请在 MySQL 提示符下运行以下命令。 别忘了用你选择的强大唯一的密码替换 password。 如果已启用 VALIDATION 插件,请确保已根据当前策略要求使用了强密码。
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'password';
使用以下命令更新数据库:
FLUSH PRIVILEGES;
使用命令再次检查身份验证方法是否已更改:
SELECT user,authentication_string,plugin,host FROM mysql.user;
输出结果:
好!MySQL root 用户就可以使用密码进行身份验证来访问 mysql shell。
从 MySQL 提示符下退出:
exit
安装 PHP 请运行:
$ sudo apt install php libapache2-mod-php php-mysql
安装 PHP 后,在 Apache 文档根目录中创建 info.php 文件。通常,在大多数基于 Debian 的 Linux 发行版中,Apache 文档根目录为 /var/www/html/ 或 /var/www/。Ubuntu 18.04 LTS 系统下,文档根目录是 /var/www/html/。
在 Apache 根目录中创建 info.php 文件:
$ sudo vi /var/www/html/info.php
在此文件中编辑如下内容:
<?php
phpinfo();
?>
然后按下 ESC 键并且输入 :wq 保存并退出此文件。重新启动 Apache 服务使更改生效。
$ sudo systemctl restart apache2
3.1 测试 PHP
打开 Web 浏览器,然后导航到 URL http://IP地址/info.php 。
你就将看到 PHP 测试页面。
通常,当用户向 Web 服务器发出请求时,Apache 首先会在文档根目录中查找名为 index.html 的文件。如果你想将 Apache 更改为 php 文件提供服务而不是其他文件,请将 dir.conf 配置文件中的 index.php 移至第一个位置,如下所示:
$ sudo vi /etc/apache2/mods-enabled/dir.conf
上面的配置文件(dir.conf) 内容如下:
<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 移动到最前面。更改后,dir.conf 文件内容看起来如下所示。
<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 保存并关闭此文件。重新启动 Apache 服务使更改生效。
$ sudo systemctl restart apache2
3.2 安装 PHP 模块
为了增加 PHP 的功能,可以安装一些其他的 PHP 模块。
要列出可用的 PHP 模块,请运行:
$ sudo apt-cache search php- | less
输出结果:
使用方向键浏览结果。要退出,请输入 q 并按下回车键。
要查找任意 php 模块的详细信息,例如 php-gd,请运行:
$ sudo apt-cache show php-gd
安装 PHP 模块请运行:
$ sudo apt install php-gd
安装所有的模块(虽然没有必要),请运行:
$ sudo apt-get install php*
安装任何 php 模块后,请不要忘记重新启动 Apache 服务。要检查模块是否已加载,请在浏览器中打开 info.php 文件并检查是否存在。
接下来,你可能需要安装数据库管理工具,以通过 Web 浏览器轻松管理数据库。如果是这样,请按照以下链接中的说明安装 phpMyAdmin。
祝贺你!我们已经在 Ubuntu 服务器中成功配置了 LAMP 套件。
via: www.ostechnix.com
作者: SK 选题: lujun9972 译者: stevenzdg988 校对: wxy
本文由 LCTT 原创编译, Linux中国 荣誉推出
*请认真填写需求信息,我们会在24小时内与您取得联系。