热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

【译】发送表单数据

这是原文链接:sendingformdata许多情况下,我们使用表单发送数据到服务器。服务器处理数据并返回响应给用户。这看起来很简单,但是

这是原文链接:sending form data

许多情况下,我们使用表单发送数据到服务器。服务器处理数据并返回响应给用户。这看起来很简单,但是了解一些细节还是很重要的,以避免损坏您的服务器或者给您的用户带来麻烦。

发送数据到哪?

客户端/服务器架构

web是基于非常简单的客户端/服务器架构的,可以总结为一下两点:

  1. 客户端(通常是浏览器)通过HTTP协议发送请求给服务器(大部分服务器就是Apache,Nginx,IIS,Tomcat)
  2. 服务器同样使用HTTP协议来返回响应

客户端/服务器端架构

在客户端,没有比表单更方便而且用户友好的方式来配置HTTP请求去发送数据到服务器端了。这使得用户可以通过HTTP请求来传递信息。

在客户端:定义怎样发送数据

表单元素定义了怎样发送数据。其所有属性就是被设计用来配置HTTP请求的。最主要的两个属性是action和method。

关于action属性
该属性定义了数据被发送到哪。其值必须是合法的URL。如果没有提供该属性,那么数据发送到当前页面。

例子

这个例子中,数据被发送到http://foo.com

这个例子中,数据被发送到相同的服务器中,但是与当前页面不同的URL

如果没有指定该属性,那么数据被发送到当前页面

许多以前的网页中使用下面的代码来指明数据应该被发送到当前页面,应为在HTML5之前,该属性是必须的,现在已经没有必要了这样写了

注意:可以指定URL使用https协议。如果这样做了,那么即使表单本身处于不安全的网页中(使用http协议),表单数据也会被加密。另一方面,如果表单本身处于安全网页中,但是指定URL使用不安全的http协议,那么每次当用户提交数据时,浏览器都会显示不安全的警告给用户,因为数据没有被加密。

关于method属性

该属性定义了数据怎样被发送。HTTP协议定义了许多种request;表单数据至少可以通过两种方法来发送:GET和POST。

为了理解两种发送方法的不同,我们先回顾一下HTTP工作原理。每次当你想要获取一个网络上的资源,浏览器会发送一个请求。这个请求包含两个部分:header和body。其中header包含了一系列的关于浏览器能力的全局元数据,body则是包含一些发送到服务器端的信息(只用部分发送方法的请求有body部分,有些请求没有body部分)。

关于GET方法
GET方法说明浏览器想要服务器端返回一个资源:“嘿,服务器,给我返回这个资源”。这种请款下,浏览器发送的请求没有body部分。因为如果表单采用这种方法发送数据,数据会被添加到URL后面,所以body是空的。

例子

考虑下面的表单:


如果使用GET方法,那么请求应该是这样的:

GET /?say=Hi&to=Mom HTTP/1.1
Host: foo.com

关于POST方法
POST方法有些不同。浏览器希望服务器处理这些数据:“嘿,服务器,看看这些数据然后给我一个结果”。发送的数据处在请求的body部分。

例子

考虑下面的表单(和上面的一样)


现在使用POST方法,那么请求应该是这样的:

POST / HTTP/1.1
Host: foo.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 13say=Hi&to=Mom

Content-Length字段指明body的大小,Content-Type字段指明发送到服务器端的资源类型(其实就是编码方式)。

当然,HTTP协议从来不会显示给用户(不过可以通过浏览器的开发者工具来查看)。唯一显示给用户的就是URL。所以在GET方法中,用户可以从网址栏中看见数据,但是在POST方法中,就看不见了。这一点非常重要:

  1. 如果将要发送用户名和密码(或者其他敏感信息),一定不能使用GET方法,否则就会在地址栏显示出来。
  2. 如果将要发送巨量数据,最好使用POST方法,应为某些浏览器会限制URL的长度,并且许多服务器也会限制可以接收的URL长度。

在服务器端:解析并获取数据

不管采用哪种请求方法,服务器端会接收到一个字符串,然后解析该字符串,得到一系列的键值对。获取这些数据的方式取决于你选择的开发平台和特定开发框架。不同的技术同样影响到重复键的处理方法;一般情况下,后接受到的优先级更大,会覆盖掉之前的数据。

例子:原生PHP

PHP提供了一些全局对象去获取这些数据。假设我们使用POST方法提交数据,下面的例子仅仅是获取这些数据然后展示给用户。当然,怎样处理这些数据取决于你。你可以显示数据,存储数据,发送邮件或者其他方式。

上面例子的结果是:

Hi Mom

例子:原生Python

本例子使用Python实现相同的功能--显示网页提供的数据。例子中使用CGI Python package来获取数据。

#!/usr/bin/env python
import html
import cgi
import cgitb; cgitb.enable() # for troubleshootingprint("Content-Type: text/html") # HTTP header to say HTML is following
print() # blank line, end of headersform = cgi.FieldStorage()
say = html.escape(form["say"].value);
to = html.escape(form["to"].value);print(say, " ", to)

显示结果和上面的例子一样:

Hi Mom

其他语言和框架

还有许多其他的服务端技术可以处理表单,包括Perl,Java,.Net,Ruby等等。选择你最喜欢的就好了。但是也没有必要直接使用这些技术去处理表单,因为会比较繁琐。更通常的做法是选择一种框架来辅助处理表单,比如:

  • Symfony for PHP
  • Django for Python
  • Ruby On Rails for Ruby
  • Grails for Java

虽然使用这些框架来处理表单不一定就是非常容易,但是总是好一些,并且可以节省大量时间。

一种特殊情况:发送文件

发送文件对表单来说是一种特殊情况。文件是二进制数据--至少被当作二进制数据--但是其他数据都是文本数据。因为HTTP协议是一种文本协议,所以处理二进制数据是特殊需求了。

enctype属性

该属性可以指定Content-Type字段的值。该字段非常重要,因为可以让服务器端识别出发送的数据类型(编码类型)。默认值是application/x-www-urlencoded。对人类而言,这意味着:“表单数据已经被编码成URL形式了”。

如果我们想要发送文件,应该需要做两件事:

  1. 设置method属性为POST,因为文件内容不能放到URL中。
  2. 设置enctype属性为multipart/form-data,这样文件会被分割成很多部分发送到服务器。

举个例子:


注意:有些浏览器的input元素支持multiple属性,从而支持一个input元素可以发送多个文件。服务器端怎样处理这些文件完全依赖与服务器端选择的技术。前面也提到过,使用框架来处理这些东西会稍微轻松些。

警告:许多服务器都限制了上传文件的大小和HTTP请求的大小,以防止滥用资源。和服务器管理员确定这个限制的大小是非常重要的。

安全问题

当你每次发送数据给服务器时,你都应该考虑安全问题。HTML表单是服务器的主要威胁之一。不过问题并不是来源于表单本身,而是服务器如何处理表单数据。

常见安全漏洞

以下是一些众所周知的安全问题:

XSS和CSRF

跨站点脚本攻击(XSS)和跨站点请求伪造(CSRF)是常见的攻击类型,这通常发生在服务器接收用户的数据然后再次显示这些数据给用户。

XSS使得攻击者可以注入客户端脚本到网页中。一个XSS漏洞可能会让攻击者可以绕过访问控制,比如同源策略。这些攻击的影响可大可小,可以是比较小的干扰,也可以是重大安全风险。

CSRF和XSS有些相似--因为他们都需要注入客户端脚本到网页中--但是CSRF的目的又不一样。CSRF攻击者会提升自己的特权(比如网站管理员),然后就可以做一些本来没有权利的操作,比如发送数据给不信任的用户。

XSS攻击利用用户对网站的信任,CSRF攻击利用网站对用户的信任。

为避免这些攻击,你应该检查用户发送到服务器的所有数据,而且不应该显示用户提供的HTML内容。相反,你应该处理这些数据而不是一字不变的显示这些数据。如今大部分框架都实现了基本的HTML字符过滤,比如过滤掉,,。这可以降低风险,但还是不能完全避免掉。

SQL注入

SQL注入是一种尝试操作网站数据库的一种攻击。攻击者通常会发送SQL请求并期望服务器去执行它(其实就是存储数据),这也是服务器的主要威胁之一。

这种攻击的后果是非常严重的,轻一点就是数据丢失,严重的就是特权提升到可以操作所有服务器资源。这种威胁是非常严峻的,所以你永远不应该直接存储用户提交的数据,而是需要做一些检查以及消毒工作(比如在PHP/MySQL应用中使用mysql_real_escape_string())。

HTTP header注入 以及 email 注入

如果你使用表单数据来建立HTTP header或者email,那么就有可能发生这些攻击。他们不会直接攻击服务器或者影响到用户,但却是更深层次问题的后门,比如会话劫持或者钓鱼攻击。

这些攻击大部分都是静悄悄的,但是却会将你的服务器变为肉鸡。

警记:永远不要相信你的用户

那么怎样处理这些威胁呢?这些内容已经超出本章内容了,但是仍然有一些规则需要牢记在心中。最最重要的规则就是:永远不要相信用户,包括自己;因为一个可信任的用户也可能被劫持。

所有到达服务器的数据都需要检查和消毒,总是这样做,不要存在例外。

  • 转义潜在的危险的字符。根据数据内容的不同以及部署平台的不同,需要小心的字符也有所区别。但是所有服务器端语言都有相关的函数来处理这种转义。
  • 限制数据的大小以及必须的类型。
  • 上传文件到沙箱(存储这些文件到一个不同的服务器,而且只允许通过一个不同的子域名来访问文件,甚至最好是完全不同的域名来访问文件)。

如果你遵守上面三条规则,你应该可以避免掉绝大部分的难题了,但是邀请第三方做一个安全审查仍然是一个好主意。永远不要假设你已经解决了所有问题。

总结

如你所见,发送表单数据是非常容易的,但是只做安全的web应用则是复杂的。要记住作为前端开发者不仅仅只是定义数据模型。我们还要做客户端的数据校验,但是服务器端仍然不能信任这些校验结果,因为服务器可没办法知道客户端的真实情况。

另请参见

下面两个链接是关于安全web应用方面的,可以继续参考学习:

  1. The Open Web Application Security Project (OWASP)
  2. Chris Shiflett's blog about PHP Security

下面是关于http方面的链接

  1. GET/POST之enctype
  2. GET vs. POST
  3. What's the difference between “Request Payload” vs “Form Data” as seen in Chrome dev tools Network tab
  4. How are parameters sent in an HTTP POST request?

个人补充

上面更多的内容是关于web安全方面的,下面补充一点method以及enctype方面的信息。

表单中method属性用来指定发送数据的方法:比如GET/POST/PUT等等
表单中enctype属性用来指定发送的数据的编码方式:比如text/plain,application/json,application/x-www-form-urlencoded,application/octet-stream,multipart/form-data等等

GET/POST/PUT最大的不同当然是语义不一样,不过这里只研究对于发送数据的影响。
GET发送的数据位于URL中的query string部分,而URL又处于请求header部分。
POST/PUT发送的数据位置倒是一样,都是位于请求body部分。

不同的method会影响到发送数据的位置,而enctype则会影响到数据的编码方式。
form元素的enctype默认值则是application/x-www-form-urlencoded,所以发送的数据可能长得像这样:

username=name123&password=pass456&age=12&sex=1

注意这种编码形式和GET/POST/PUT是没有关系的。只不过如果是GET方法,那么URL加上问号(?)再加上数据拼接起来。如果是POST/PUT方法,那么数据就存放在请求body部分。

对于jquery中的ajax方法的contentType默认值也是application/x-www-form-urlencoded。
而在backbone中,Backbone.sync方法中有一段代码会做出判断,可能会将contentType设置为application/json。

先说说multipart/form-data,一般在上传文件的时候,需要将表单的enctype设置为multipart/form-data。正如上面译文中所讲,文件属于二进制数据,application/x-www-form-urlencoded是不适用的。
不过这种编码方式过于复杂,不像上面的urlencoded编码,只需要两次分割字符串就能得到所有的键值对。对于这种复杂的编码方式,我们自己去解析数据,是很难的,幸好已经有开源的库完成了这一部分功能。
对于单文件上传也许还好,自己了解编码方式以后,解析起来也不是很难。难点在于多文件上传,甚至还有普通表单控件混在其中。

再说说application/json,据我理解urlencoded编码方式只适用于扁平化的键值对,对于嵌套过深的json对象就很难编码了。而application/json就非常适用于嵌套过深的json数据。
在chrome的开发者工具中的network页签中,显示发送数据位于Request Payload。而如果是application/x-www-form-urlencoded,就会显示发送数据位于Form Data。

实际上是可以自定义contentType的,也就是自定义编解码的规则。不过只针对ajax有效,对于form元素是不起作用的。因为form元素的编码规则有浏览器控制。而对于ajax,我们完全可以自己编码,然后在服务器端自己解码。

最后一点,如果服务器端不能理解Content-Type指定的编码方式,那么应该返回415错误。

转:https://www.cnblogs.com/3tree/p/4584302.html



推荐阅读
  • 本文介绍了南邮ctf-web的writeup,包括签到题和md5 collision。在CTF比赛和渗透测试中,可以通过查看源代码、代码注释、页面隐藏元素、超链接和HTTP响应头部来寻找flag或提示信息。利用PHP弱类型,可以发现md5('QNKCDZO')='0e830400451993494058024219903391'和md5('240610708')='0e462097431906509019562988736854'。 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • Windows下配置PHP5.6的方法及注意事项
    本文介绍了在Windows系统下配置PHP5.6的步骤及注意事项,包括下载PHP5.6、解压并配置IIS、添加模块映射、测试等。同时提供了一些常见问题的解决方法,如下载缺失的msvcr110.dll文件等。通过本文的指导,读者可以轻松地在Windows系统下配置PHP5.6,并解决一些常见的配置问题。 ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • [译]技术公司十年经验的职场生涯回顾
    本文是一位在技术公司工作十年的职场人士对自己职业生涯的总结回顾。她的职业规划与众不同,令人深思又有趣。其中涉及到的内容有机器学习、创新创业以及引用了女性主义者在TED演讲中的部分讲义。文章表达了对职业生涯的愿望和希望,认为人类有能力不断改善自己。 ... [详细]
  • http:my.oschina.netleejun2005blog136820刚看到群里又有同学在说HTTP协议下的Get请求参数长度是有大小限制的,最大不能超过XX ... [详细]
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
  • 在重复造轮子的情况下用ProxyServlet反向代理来减少工作量
    像不少公司内部不同团队都会自己研发自己工具产品,当各个产品逐渐成熟,到达了一定的发展瓶颈,同时每个产品都有着自己的入口,用户 ... [详细]
  • 个人学习使用:谨慎参考1Client类importcom.thoughtworks.gauge.Step;importcom.thoughtworks.gauge.T ... [详细]
  • springmvc学习笔记(十):控制器业务方法中通过注解实现封装Javabean接收表单提交的数据
    本文介绍了在springmvc学习笔记系列的第十篇中,控制器的业务方法中如何通过注解实现封装Javabean来接收表单提交的数据。同时还讨论了当有多个注册表单且字段完全相同时,如何将其交给同一个控制器处理。 ... [详细]
  • Nginx使用AWStats日志分析的步骤及注意事项
    本文介绍了在Centos7操作系统上使用Nginx和AWStats进行日志分析的步骤和注意事项。通过AWStats可以统计网站的访问量、IP地址、操作系统、浏览器等信息,并提供精确到每月、每日、每小时的数据。在部署AWStats之前需要确认服务器上已经安装了Perl环境,并进行DNS解析。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • 本文介绍了OC学习笔记中的@property和@synthesize,包括属性的定义和合成的使用方法。通过示例代码详细讲解了@property和@synthesize的作用和用法。 ... [详细]
  • 知识图谱——机器大脑中的知识库
    本文介绍了知识图谱在机器大脑中的应用,以及搜索引擎在知识图谱方面的发展。以谷歌知识图谱为例,说明了知识图谱的智能化特点。通过搜索引擎用户可以获取更加智能化的答案,如搜索关键词"Marie Curie",会得到居里夫人的详细信息以及与之相关的历史人物。知识图谱的出现引起了搜索引擎行业的变革,不仅美国的微软必应,中国的百度、搜狗等搜索引擎公司也纷纷推出了自己的知识图谱。 ... [详细]
  • ZSI.generate.Wsdl2PythonError: unsupported local simpleType restriction ... [详细]
author-avatar
好人杨华_840
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有