摘要:若該特性未指定,則數(shù)據(jù)會(huì)發(fā)送到包含該表單的頁(yè)面所在的。其中使用了來(lái)處理表單數(shù)據(jù)。特殊案例發(fā)送文件文件是表單中一個(gè)特殊的例子,其他數(shù)據(jù)都是文本數(shù)據(jù),而文件則一般是或者被認(rèn)為是二進(jìn)制數(shù)據(jù)。
系列文章說(shuō)明
原文
多數(shù)時(shí)候,HTML表單的目的只是為了把數(shù)據(jù)發(fā)給服務(wù)器,之后服務(wù)器再處理這些數(shù)據(jù)并發(fā)送響應(yīng)給用戶。雖然看起來(lái)挺簡(jiǎn)單的,但我們還是得注意一些事情以確保傳送的數(shù)據(jù)不會(huì)破壞服務(wù)器、或者給你的用戶制造麻煩。
數(shù)據(jù)會(huì)到哪里去 關(guān)于客戶端/服務(wù)器架構(gòu)整個(gè)web都是基于一種基本的客戶端/服務(wù)器架構(gòu),該架構(gòu)可以歸納如下:
一個(gè)客戶端(通常是Web瀏覽器)使用HTTP協(xié)議發(fā)送一個(gè)請(qǐng)求給服務(wù)器(通常是web服務(wù)器程序,譬如Apache, Nginx, IIS, Tomcat等等),而服務(wù)器則以相同的協(xié)議響應(yīng)這個(gè)請(qǐng)求。
在客戶端,HTML表單只是提供一種比較方便且用戶友好的方式,用來(lái)配置發(fā)送給服務(wù)器的HTTP請(qǐng)求。這樣用戶就可以自己提供能被HTTP請(qǐng)求傳送的信息。
客戶端:定義如何發(fā)送數(shù)據(jù)元素能夠定義其數(shù)據(jù)如何被發(fā)送,它所有的特性都是為了在用戶點(diǎn)擊發(fā)送按鈕時(shí),讓你配置要發(fā)送的請(qǐng)求。其中最重要的兩個(gè)特性是action和method。
action特性該特性定義了數(shù)據(jù)會(huì)被發(fā)往何處,它的值必須是個(gè)合法的URL。若該特性未指定,則數(shù)據(jù)會(huì)發(fā)送到包含該表單的頁(yè)面所在的URL。
示例
在下面的例子中,數(shù)據(jù)會(huì)發(fā)送至http://foo.com:
使用GET方法時(shí),HTTP請(qǐng)求看起來(lái)就這樣:
GET /?say=Hi&to=Mom HTTP/1.1 Host: foo.com
POST方法則稍有不同,瀏覽器發(fā)送這個(gè)方法給服務(wù)器,用以請(qǐng)求一個(gè)和HTTP請(qǐng)求體里數(shù)據(jù)有關(guān)的響應(yīng):“嘿服務(wù)器,看看這些數(shù)據(jù)然后給我發(fā)回一個(gè)適當(dāng)?shù)慕Y(jié)果”。若表單使用該方法發(fā)送,則數(shù)據(jù)會(huì)給追加到HTTP請(qǐng)求體里。
示例
考慮如下表單(和上面那個(gè)一樣):
使用POST方法時(shí),HTTP請(qǐng)求看起來(lái)就這樣:
POST / HTTP/1.1 Host: foo.com Content-Type: application/x-www-form-urlencoded Content-Length: 13 say=Hi&to=Mom
Content-length頭部字段指示了請(qǐng)求體的大小,而Content-Type字段則標(biāo)識(shí)了發(fā)往服務(wù)器的資源類型。我們將在稍后討論下這些請(qǐng)求頭。
當(dāng)然,HTTP請(qǐng)求是不會(huì)展示給用戶看的(若你想看到它們,還得使用諸如火狐的Web Console或者chrome Developer Tools等工具),唯一展示給用戶的,只有訪問(wèn)的URL。所以使用GET請(qǐng)求時(shí),用戶將會(huì)在他們的地址欄看到數(shù)據(jù),而使用POST請(qǐng)求則看不到。這點(diǎn)至關(guān)重要,原因如下:
若你要發(fā)送密碼(或者任何敏感數(shù)據(jù)),那千萬(wàn)別用GET方法,否則該數(shù)據(jù)會(huì)不安全地展示在地址欄上。
若你想要發(fā)送大量數(shù)據(jù),最好用POST方法,因?yàn)橐恍g覽器會(huì)限制URL的大小。此外,許多服務(wù)器也會(huì)限制接收的URL長(zhǎng)度。
服務(wù)器端:處理數(shù)據(jù)不論你選擇哪種HTTP方法,服務(wù)器只會(huì)接收到一個(gè)字符串并將其解析,再以鍵/值對(duì)列表的形式獲取數(shù)據(jù)。而如何訪問(wèn)這個(gè)列表,取決于你基于何種開(kāi)發(fā)平臺(tái)、以及用了何種框架。你使用的技術(shù)也會(huì)決定如何處理重復(fù)的鍵名,通常某個(gè)鍵名最后接收到的值是優(yōu)先被選取的。
示例:原生PHPPHP提供了幾個(gè)全局對(duì)象來(lái)處理數(shù)據(jù)。假設(shè)你使用POST方法,下面的示例會(huì)直接提取你的數(shù)據(jù)并展示給用戶。當(dāng)然,要如何處理數(shù)據(jù)取決于你,你可以展示它、將其存進(jìn)數(shù)據(jù)庫(kù)、用郵件發(fā)送它、或者其他任何方式。
這個(gè)示例會(huì)用我們發(fā)送的數(shù)據(jù)生成一個(gè)頁(yè)面??紤]我們前面用的表單示例數(shù)據(jù),輸出結(jié)果會(huì)是:
Hi Mom示例:原生Python下面的示例使用Python來(lái)做相同的事---將給定的數(shù)據(jù)展示到web頁(yè)面上。其中使用了CGI Python package 來(lái)處理表單數(shù)據(jù)。
#!/usr/bin/env python import html import cgi import cgitb; cgitb.enable() # 用于處理錯(cuò)誤 print("Content-Type: text/html") # 請(qǐng)求頭字段,標(biāo)識(shí)后面的內(nèi)容是HTML print() # 空行,表示請(qǐng)求頭的結(jié)束 form = cgi.FieldStorage() say = html.escape(form["say"].value); to = html.escape(form["to"].value); print(say, " ", to)結(jié)果和之前用PHP處理是一樣的:
Hi Mom其它語(yǔ)言和框架還有許多其他的服務(wù)端技術(shù)可以用來(lái)處理表單,比如Perl, Java, .Net, Ruby等等,選擇你最喜歡的一種就好。我們很少直接使用這些技術(shù),因?yàn)檫@么做得需要很多技巧來(lái)填坑;通常我們會(huì)在眾多好用的框架中選擇一種,這樣會(huì)讓表單的處理更容易些,比如:
Symfony for PHP
Django for Python
Ruby On Rails for Ruby
Grails for Java
值得注意的是,就算用了這些框架,處理表單是不一定就會(huì)變得輕松。但至少這樣用起來(lái)會(huì)更好些,還能節(jié)省你不少時(shí)間。
特殊案例:發(fā)送文件文件是HTML表單中一個(gè)特殊的例子,其他數(shù)據(jù)都是文本數(shù)據(jù),而文件則一般是、或者被認(rèn)為是二進(jìn)制數(shù)據(jù)。由于HTTP是個(gè)文本協(xié)議,所以對(duì)處理二進(jìn)制數(shù)據(jù)得有特別的要求。
enctype特性該特性能讓你指定HTTP請(qǐng)求頭中的Content-Type字段值,這個(gè)字段的重要性在于,它能告訴服務(wù)器要發(fā)送的數(shù)據(jù)類型。其默認(rèn)值是application/x-www-form-urlencoded,對(duì)應(yīng)的解釋是:“這份表單數(shù)據(jù)已被編碼為URL格式”。
而當(dāng)你想發(fā)送文件時(shí),得先做兩件事:
將method特性設(shè)置為POST,因?yàn)槭褂帽韱螘r(shí),文件內(nèi)容是不能被放到URL參數(shù)里的
將enctype特性的值設(shè)為multipart/form-data,這樣數(shù)據(jù)就會(huì)被分割為多個(gè)部分,每個(gè)文件都會(huì)追加上和他們一起發(fā)送的表單有關(guān)的文本。
示例:
安全相關(guān)注意:某些瀏覽器支持元素的multiple特性,以便讓一個(gè)input元素能發(fā)送多個(gè)文件。至于服務(wù)器會(huì)如何處理這些文件,就得取決于它用來(lái)什么技術(shù)了。如前所述,使用框架能讓你的活的輕松些~
警告:為防止濫用,許多服務(wù)器會(huì)對(duì)文件和HTTP請(qǐng)求設(shè)置大小限制。所以,最好在發(fā)送文件之前和服務(wù)器管理員核實(shí)一下這個(gè)限制。
每次要發(fā)數(shù)據(jù)給服務(wù)器前,你都得考慮下安全問(wèn)題。HTML表單是針對(duì)服務(wù)器的首要攻擊載體之一,但該危害的來(lái)源并非HTML表單本身,而在于服務(wù)器如何處理數(shù)據(jù)。
常見(jiàn)的安全問(wèn)題著名的安全問(wèn)題有很多,如何劃分取決于你在做什么:
XSS和CSRF跨站腳本攻擊(XSS)和跨站請(qǐng)求偽造(CSRF)是最常見(jiàn)的攻擊類型,它們會(huì)在你展示由用戶發(fā)給用戶的數(shù)據(jù)時(shí)發(fā)生。
XSS讓攻擊者能再其他用戶訪問(wèn)的Web頁(yè)面上注入客戶端腳本。攻擊者會(huì)利用跨站腳本的脆弱性來(lái)繞過(guò)訪問(wèn)控制策略,譬如同源策略。這種攻擊可以取得從小麻煩到嚴(yán)重安全危機(jī)不等的危害效果。
CSRF很像XSS,因?yàn)樗鼈兌家韵嗤姆绞介_(kāi)始---注入客戶端腳本到Web頁(yè)面,但它們的攻擊目標(biāo)卻不同。CSRF攻擊者會(huì)試著升級(jí)權(quán)限以成為一個(gè)高權(quán)限的用戶(比如網(wǎng)站管理員),然后執(zhí)行本不能夠執(zhí)行的動(dòng)作(如把數(shù)據(jù)發(fā)送給不受信任的用戶)。
XSS攻擊利用了用戶對(duì)網(wǎng)站的信任,而CSRF攻擊則利用了網(wǎng)站對(duì)其用戶的信任。
要防止此類攻擊,就得時(shí)常校驗(yàn)用戶發(fā)送給服務(wù)器的數(shù)據(jù);同時(shí)(如果需要展示)也盡量別展示用戶提供的HTML內(nèi)容,而應(yīng)該處理用戶提供的數(shù)據(jù),以避免將其原封不動(dòng)地顯示出來(lái)。目前幾乎所有市面上的的框架,至少都會(huì)實(shí)現(xiàn)一個(gè)過(guò)濾器,用以移除用戶提交數(shù)據(jù)中, , 等標(biāo)簽,這樣有助于減輕風(fēng)險(xiǎn),但并不意味著會(huì)根除它。
SQL注入SQL注入是一種對(duì)目標(biāo)網(wǎng)站的數(shù)據(jù)庫(kù)執(zhí)行動(dòng)作的攻擊方式。通常攻擊者會(huì)發(fā)送一段SQL請(qǐng)求,并希望服務(wù)器能執(zhí)行它(多數(shù)發(fā)生在應(yīng)用服務(wù)器想存儲(chǔ)數(shù)據(jù)之時(shí))。這實(shí)際上已成為針對(duì)web站點(diǎn)的主要攻擊載體之一。
該攻擊的危害是很嚴(yán)重的,小到數(shù)據(jù)丟失、大到被攻擊者通過(guò)權(quán)限升級(jí)訪問(wèn)整個(gè)網(wǎng)站架構(gòu)。這確實(shí)是非常重大的威脅,所以你不應(yīng)該存儲(chǔ)那些用戶提交而沒(méi)經(jīng)過(guò)特殊處理(例如,在PHP/MySQL架構(gòu)下經(jīng)過(guò)mysql_real_escape_string()處理)的數(shù)據(jù)。
HTTP頭部注入和郵件注入這種攻擊會(huì)在你的應(yīng)用使用用戶在表單上輸入的數(shù)據(jù)來(lái)構(gòu)造HTTP頭、或者email時(shí)發(fā)生。該攻擊雖然不會(huì)危害你的服務(wù)器或者影響你的用戶,但卻會(huì)給更深處的問(wèn)題大開(kāi)方便之門,比如會(huì)話劫持、釣魚攻擊。
所有這些攻擊往往都是悄無(wú)聲息地發(fā)生的,而且會(huì)把你的服務(wù)器弄成肉雞)。
偏執(zhí)些:永遠(yuǎn)別信任你的用戶所以,要如何對(duì)抗這些威脅呢?這一點(diǎn)已超出本指南的主題范圍了,但有幾條規(guī)則時(shí)需要我們牢記的。最重要的一條就是:永遠(yuǎn)別信任你的用戶,包括你自己;即使是受信任的用戶也會(huì)有被劫持可能。
所有的到達(dá)你服務(wù)器的數(shù)據(jù)都必須被校驗(yàn)并處理,而且要一直保持,不能有例外。
過(guò)濾潛在的危險(xiǎn)字符。要關(guān)注的哪些特定字符,取決于使用數(shù)據(jù)的上下文、也取決于你使用的服務(wù)器平臺(tái),而所有的服務(wù)端語(yǔ)言都會(huì)提供相應(yīng)的功能。
限制傳入的數(shù)據(jù)量,只允許有必要的。
把上傳的文件放沙盒里(將它們存儲(chǔ)到放到一個(gè)不同的服務(wù)器上,并且要訪問(wèn)到它們只有通過(guò)一個(gè)不同的子域名、或一個(gè)完全不同的域名才行)。
若你能遵循這三條規(guī)則,就應(yīng)該能避免絕大多數(shù)問(wèn)題,但一個(gè)更好的辦法是讓一個(gè)有資格的第三方來(lái)做安全審查,別以為你能看透所有潛在的問(wèn)題。
結(jié)論如你所見(jiàn),發(fā)送表單數(shù)據(jù)時(shí)很簡(jiǎn)單的,但保障一個(gè)應(yīng)用的安全就需要很多技術(shù)了。前端開(kāi)發(fā)者不是那種去定義一個(gè)數(shù)據(jù)安全模型的角色,雖然可能得執(zhí)行[客戶端數(shù)據(jù)校驗(yàn)](),但是服務(wù)器也不能信任這些校驗(yàn),因?yàn)樗⒉荒艽_切知道客戶端上到底發(fā)生過(guò)什么。
參見(jiàn)若你想學(xué)習(xí)更多關(guān)于wep應(yīng)用安全防護(hù)的知識(shí),可以深入了解下面這些資源:
The Open Web Application Security Project (OWASP)
Chris Shiflett"s blog about PHP Security
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/50090.html
摘要:之前我們已經(jīng)看到在中我們可以給規(guī)則指定方法對(duì)應(yīng)的函數(shù)可以按字典形式接收表單數(shù)據(jù)然后將這些數(shù)據(jù)輸送到模板中并最終渲染為網(wǎng)頁(yè)在下面的例子中渲染一個(gè)含有表單的網(wǎng)頁(yè)填入到表單的數(shù)據(jù)被到然后觸發(fā)了函數(shù)函數(shù)將表單數(shù)據(jù)組裝起來(lái)放入字典對(duì)象中然后發(fā)送到模板 之前我們已經(jīng)看到在Flask中我們可以給URL規(guī)則指定http方法, 對(duì)應(yīng)的函數(shù)可以按字典形式接收表單數(shù)據(jù), 然后將這些數(shù)據(jù)輸送到模板中并最終渲染...
摘要:用表單中創(chuàng)建一個(gè)對(duì)象要用現(xiàn)有的元素建立一個(gè)對(duì)象,可以在建立對(duì)象時(shí)傳入指定的元素。通過(guò)提交表單和發(fā)送文件而不使用對(duì)象若你想了解如何基于進(jìn)行序列化和發(fā)送表單操作,而不使用對(duì)象,可閱讀此文。 系列文章說(shuō)明 原文 FormData對(duì)象能讓你生成一系列用于XMLHttpRequest發(fā)送的鍵值對(duì)。它主要的目的在于發(fā)送表單數(shù)據(jù),但也能獨(dú)立用于傳輸有鍵形式的數(shù)據(jù)。其傳輸?shù)臄?shù)據(jù)格式和表單使用sub...
摘要:用表單中創(chuàng)建一個(gè)對(duì)象要用現(xiàn)有的元素建立一個(gè)對(duì)象,可以在建立對(duì)象時(shí)傳入指定的元素。通過(guò)提交表單和發(fā)送文件而不使用對(duì)象若你想了解如何基于進(jìn)行序列化和發(fā)送表單操作,而不使用對(duì)象,可閱讀此文。 系列文章說(shuō)明 原文 FormData對(duì)象能讓你生成一系列用于XMLHttpRequest發(fā)送的鍵值對(duì)。它主要的目的在于發(fā)送表單數(shù)據(jù),但也能獨(dú)立用于傳輸有鍵形式的數(shù)據(jù)。其傳輸?shù)臄?shù)據(jù)格式和表單使用sub...
摘要:一個(gè)表單由一或多個(gè)部件組成,這些部件可以是文本框單行或多行選擇框按鈕復(fù)選框或單選按鈕。在我們的示例里,一個(gè)文本框中用了該屬性的默認(rèn)值,該值表示一個(gè)基本的單行文本框,用于接收無(wú)控制或驗(yàn)證的任何文本。 前言 這個(gè)系列譯自mdn上的一份表單指南,原文詳盡闡述了表單相關(guān)的基礎(chǔ)知識(shí)。而表單作為一個(gè)經(jīng)典的頁(yè)面交互方式,是每個(gè)前端工程師繞不開(kāi)的話題,通過(guò)翻譯這個(gè)系列的文章既是有助于掃清自己的知識(shí)盲區(qū)...
摘要:能異步地發(fā)送任意數(shù)據(jù)的技術(shù)稱為,表示異步的和。若你使用,使用發(fā)送表單還會(huì)影響同源策略,并導(dǎo)致內(nèi)容被發(fā)送到一個(gè)無(wú)法訪問(wèn)的中。但要手動(dòng)發(fā)送二進(jìn)制數(shù)據(jù)的話,還有很多額外工作要做。用來(lái)發(fā)送二進(jìn)制是很直接的,使用方法就好了。 系列文章說(shuō)明 原文 在[發(fā)送表單數(shù)據(jù)]()一文中,HTML表單可以聲明式地發(fā)送一個(gè)HTTP請(qǐng)求。但表單也可以用JavaScript來(lái)準(zhǔn)備一個(gè)HTTP請(qǐng)求。本文將探索如何...
閱讀 1081·2021-11-23 09:51
閱讀 2762·2021-08-23 09:44
閱讀 712·2019-08-30 15:54
閱讀 1489·2019-08-30 13:53
閱讀 3157·2019-08-29 16:54
閱讀 2594·2019-08-29 16:26
閱讀 1254·2019-08-29 13:04
閱讀 2379·2019-08-26 13:50