HTTP协议冷知识大全

若是不用HTTPS,HTTP协议如何安全的传输密码信息?

HTTP协议是纯文本协议,没有任何加密措施。经过HTTP协议传输的数据均可以在网络上被彻底监听。若是用户登录时将用户名和密码直接明文经过HTTP协议传输过去了,那么密码可能会被黑客窃取。 一种方法是使用非对称加密。GET登录页面时,将公钥以Javascript变量的形式暴露给浏览器。而后用公钥对用户的密码加密后,再将密码密文、用户名和公钥一块儿发送给服务器。服务器会提早存储公钥和私钥的映射信息,经过客户端发过来的公钥就能够查出对应的私钥,而后对密码密文进行解密就能够还原出密码的明文。 为了增强公钥私钥的安全性,服务器应该动态生成公钥私钥对,而且使用后当即销毁。可是动态生成又是很是耗费计算资源的,因此通常服务器会选择Pool方法提供有限数量的公钥私钥对池,而后每隔一段时间刷新一次Pool。javascript

文件路径攻击

不少操做系统都会使用..符号表示上层目录。若是黑客在URL的路径里面使用..符号引用上层目录,而服务器没有作好防范的话就有可能致使黑客能够直接访问权限以外的文件。好比使用多级..符号就能够引用到根目录,进一步就能够访问任意文件。 因此不少服务器都禁止在URL路径里出现..符号以免被攻击。 文件路径攻击也是不少黑客很是喜好使用的攻击方法之一。若是你的服务器有必定的访问量,打开你的nginx日志,你就会偶尔发现有一些奇怪的URL里面有一堆..符号,这种URL的出现就表示网络上的黑客正在尝试攻击你的服务器。css

DNS欺骗

HTTP协议严重依赖于DNS域名解析。任意一个域名类网址的访问都须要通过域名解析的过程获得目标服务的IP地址才能成功继续下去。 若是掌管DNS服务的运营商做恶将域名解析到不正确的IP,指向一个钓鱼的网页服务。用户若是没有觉察,就可能会将本身的敏感信息提交给冒牌的服务器。前端

谨慎使用外部的HTTP代理

HTTP代理做为客户端到服务器之间的中间路由节点,它起到传话人和翻译官的角色。 若是这个翻译官不靠谱的话,客户端是会拿到错误的返回数据的。它同DNS欺骗同样,是能够对客户端进行钓鱼攻击的。 若是这个翻译官口风不严的话,它可能会将它听到的敏感信息泄露给别人。java

413 Request Entity Too Large

客户端上传图片太大超过服务器限制时,服务器返回413错误。nginx

414 Request-URI Too Long

客户端访问的URI太长,超出了服务器容许限制,服务器返回414错误。json

202 Accepted

经常使用于异步请求。客户端发送请求到服务器,服务器当即返回一个202 Accepted表示已经成功接收到客户端的请求。 后面怎么处理由服务器本身决定,通常服务器会给客户端预留一个能够查询处理状态的接口,客户端能够选择轮训该接口来知道请求的处理进度和结果。后端

POST提交数据的方式

application/x-www-form-urlencodedapi

提交数据表单时常用,Body内部存放的是转码后的键值对。跨域

POST http://xyz.com HTTP/1.1
Content-Type: application/x-www-form-urlencoded;charset=utf-8

a=1&b=2&c=3&c=4
复制代码

application/json浏览器

提交结构化表单时使用,Body内部存放的是JSON字符串。ElasticSearch的查询协议使用的是这种方式。

POST http://xyz.com HTTP/1.1
Content-Type: application/json;charset=utf-8

{"a": 1, "b": 2, "c": [3, 4]}
复制代码

multipart/form-data

上传文件时常用。这种格式比较复杂,它是为了支持多文件上传混合表单数据而设计的一种特殊的格式。

<form action="http://example.com/upload" method="post" enctype="multipart/form-data">
  <p><input type="text" name="key1" value="value1">
  <p><input type="text" name="key2" value="value2">
  <p><input type="file" name="file1">
  <p><input type="file" name="file2">
  <p><button type="submit">Submit</button>
</form>
复制代码

用户填充了表单设置了待上传的文件,点击Submit,传输数据大体以下

POST /upload HTTP/1.1
Content-Length:xxxxx
Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryKOThiwE6HubGib7j
Host:example.com
------WebKitFormBoundaryKOThiwE6HubGib7j
Content-Disposition: form-data; name="key1"

value1
------WebKitFormBoundaryKOThiwE6HubGib7j
Content-Disposition: form-data; name="key2"

value2
------WebKitFormBoundaryKOThiwE6HubGib7j
Content-Disposition: form-data; name="file1"; filename="file1name.png"
Content-Type: image/png

file1 content here
------WebKitFormBoundaryKOThiwE6HubGib7j
Content-Disposition: form-data; name="file2"; filename="file2name.jpeg"
Content-Type: image/jpeg

file2 content here
------WebKitFormBoundaryKOThiwE6HubGib7j--
复制代码

Cookie

浏览器请求的Cookie中每每会携带敏感信息。服务器通常会将当前用户的会话ID存在cookie里,会话的具体内容存在服务器端,会话的内容很敏感。

浏览器请求时会携带Cookie信息,服务器根据Cookie信息中的会话ID找到对应的会话内容。会话内容里可能存储了用户的权限信息,拿到这部分权限信息后就可能随意控制修改用户的数据。

由于HTTP协议的不安全性,请求数据包很容易被窃听,Cookie中的会话信息很容易被盗。解决方案之一就是在会话中记录用户的终端信息和IP地址信息,若是这些信息忽然发生改变,须要强制用户从新认证。

不太高级的黑客是能够伪造出和用户真实请求一摸同样的数据包的。最完全的解决方案仍是采用HTTPS协议。

普通的Cookie信息能够经过Javascript脚本获取到。若是黑客经过某种方式在网页中植入不安全的脚本,将用户的Cookie拿到而后发送到远程的第三方服务器中,那么Cookie中的信息就被泄露了。

Cookie的两个重要属性

Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT; Secure; HttpOnly
复制代码

被标记为Secure的Cookie信息在HTTP请求中不会被传送,它只会在HTTPS请求中传送,避免数据被泄露。

被标记为HttpOnly的Cookie信息是没法经过Javascript API获取到的,它只会在请求中传送。这样能够避免黑客经过网页脚本方式窃取Cookie中的敏感信息。

Cookie(甜点)如此好吃,黑客们总想经过Cookie作各类文章。

CSRF(Cross-Site Request Forgery)

CSRF跨站请求伪造有不少别名,好比One-Click Attack(一键攻击),好比Session Riding(搭便车攻击)

假设在在一个社区博客网站中,删除我的的文章只须要一个URL就能够,Cookie中的会话权限信息会自动附加到请求上。

# 123456为文章的ID
http://example.com/blog/123456/delete
复制代码

那么当别人伪造了一个上面的连接地址诱惑你去点击,好比经过站内信件、私聊、博客评论、图片连接或者在别的什么网站上随机制造的一个连接。你不经意点了一下,就丢了你的文章。因此它被称为一键攻击。由于这是借用了你当前登录的会话信息来搞事,因此也被称为搭便车攻击。

若是在一个金融系统中,转帐要是也能够经过一个简单的URL进行的话,那这种危险就非同小可。

这就要求修改性的操做务必不得使用简单的GET请求进行处理。可是即便这种状况下你改为了POST请求,黑客依然有办法伪造请求,那就是经过iframe。

黑客在别的什么网站上伪造了一个POST表单,诱惑你去submit。若是只是普通的内嵌进HTML网页的表单,用户提交时会出现跨域问题。由于当前网站的域名和表单提交的目标域名不一致。可是若是经过iframe来内嵌表单,则能够绕过跨域的问题,而用户却彻底没有任何觉察。

为了防范CSRF攻击,聪明的网站的POST表单里都会带上CSRF_TOKEN这个隐藏字段。CSRF_TOKEN是根据用户的会话信息生成的。当表单提交时,会将token和用户的会话信息作比对。若是匹配就是有效的提交请求。

<form method="POST" action="/blog/delete">
<label for="blog_id">博客ID</label>
<input type="text" name="blog_id" value="12345">
<input type="hidden" name="csrf_token" value="xxxxxxxxxxxx">
</form>
复制代码

黑客必须拿到CSRF_TOKEN才能够借用用户的会话信息实施CSRF攻击,可是CSRF_TOKEN又必须由用户的会话信息才能够生成。黑客没有用户的会话信息,从而没法实施CSRF攻击。

XSS(Cross Site Scripting)

若是黑客能够在你的网页中植入任意Javascript脚本,那他就能够随意鱼肉你的帐户。经过Javascript能够获取Cookie的信息,能够借用你的会话去调用一些隐秘的API,而这一些行为都是在偷偷的进行,你根本彻底不知道。

<div>
# 用户内容Start
<script>send_to_hacker(document.cookie)</script>
# 用户内容END
</div>
复制代码

这类攻击在一些UGC网站中很是常见,常见的博客类网站就是UGC网站,用户能够经过编辑内容来生成网页。

黑客也是用户。他能够编辑一段Javascript脚本做为内容提交上去。若是服务器没有作好防范,这段脚本就会在生成的网页中运行起来。当其它用户在登录的状态下来浏览这个网页的时候,就悲剧了。

防范XSS通常是经过对输出的内容进行内容替换作到的。在HTML页面中不一样的位置会有不一样的内容替换规则。 比较常见的是使用HTML entity编码将HTML标签之间的内容中的一些特殊的字符进行转码。

<div>
# safe now
&lt;script&gt;send_to_hacker(document.cookie)&lt;/script&gt;
</div>
复制代码

还有些UGC内容在HTML标签的属性中、Javascript的变量中、URL、css代码中,他们转码的规则并不同,具体方法能够去Google相关文档。

跨域

跨域是个很头痛的问题。

当你有多个后端服务,可是只有一个前端的时候,你想作先后端分离,就会遇到跨域问题。你发现你的前端js调用后端服务时控制台告诉你不ok。而后只好把这些服务都挂在了同一个nginx域名下面,经过url前缀区分。

这时候你会想,跨域太TM讨厌了。既然跨域这么讨厌,那为何浏览器非要限制跨域呢?

仍是安全缘由。

让咱们回到上文的搭便车攻击(Session Riding),也就是骑着别人的会话来搞事情。

假设如今你的浏览器开了一个站点A,登录了进去,因而cookie便记录了会话id。 而后你又不当心开了另外一个站点B,这个站点页面一打开就开始执行一些恶意代码。这些代码的逻辑是调用站点A的API来获取站点A的数据,由于能够骑着(Ride)站点A的会话cookie。而这些数据正好是用户私密性的。因而用户在站点A上的私有信息就被站点B上的代码窃走了。这就是跨域的风险。

可是有时候咱们又但愿共享数据给不一样的站点,该怎么办呢?

答案是JSONP & CORS

JSONP(JSON Padding)

JSONP经过HTML的script标记实现了跨域共享数据的方式。JSONP经过在网页里定义一个回调方法,而后在页面上插入一个动态script标签,指向目标调用地址。服务器会返回一段javascript代码,通常是some_callback(data)这种形式的回调。该段代码会在浏览器里自动执行,因而网页就获得了跨域服务器返回的数据。

<script>
function some_callback(data) {
    console.log(data)
}
</script>
<script src="http://example.com/someapi?callback=some_callback"></script>
复制代码

由于JSONP是不携带cookie信息的,因此能有效避免搭便车攻击。JSONP是否能够获取到数据还须要服务器对这种调用提供显示支持,服务器必须将数据以javascript代码的形式返回才能够传递给浏览器。

CORS(Cross-Origin Resource Sharing)

JSONP的不足在于它只能发送GET请求,而且不能携带cookie。而CORS则能够发送任意类型的请求,能够选择性携带cookie。

CORS是经过Ajax发送的跨域请求技术。CORS的请求分为两种,一种是简单请求,一种是复杂请求。简单请求就是头部不多很简单的GET/HEAD/POST请求。复杂请求就是非简单请求。

浏览器发现Ajax的请求是跨域的,就会在请求头添加一个Origin参数,指明当前请求的发起站点来源。服务器根据Origin参数来决定是否受权。

若是是简单请求,Ajax直接请求服务器。服务器会当成普通的请求直接返回内容,不一样的是还会在响应头部添加几个重要的头部,其中最重要的头部是Access-Control-Allow-Origin: http://example.com

浏览器若是在响应中没有读到这个头部,就会通知Ajax请求失败。虽然服务器返回了数据,浏览器也不让脚本读到数据,这就保证了跨域的安全。服务器就是经过请求的Origin参数来决定要不要响应Access-Control-Allow-Origin头部来决定是否容许指定网站的跨域请求。

若是是复杂请求,要走一个预检的流程。预检就是浏览器先向服务器发送一个Method为Options的请求,若是服务器容许跨域请求,浏览器再发起这个Ajax请求。因此CORS的复杂请求会比简单请求额外耗费一个TTL的时间。

CORS的细节请参见大神阮一峰的博文《跨域资源共享CORS详解》

阅读相关文章,关注公众号【码洞

相关文章
相关标签/搜索