请求相关总结(HTTP,跨域,安全)

1,197 阅读15分钟

总结了一些前端请求相关知识。

HTTP官方文档参见MDN

HTTP

大致的HTTP请求过程:

1、 输入Url,第一次登陆的时候会本地留一个cookie
2、 查看缓存,包括浏览器->系统缓存->路由缓存,存在缓存则显示
3、 DNS域名解析,解析域名获得IP地址,而后根据IP地址向服务器发起tcp链接,建立三次握手。
4、 握手成功后浏览器向服务器发送http请求,请求数据包。
5、 服务器处理请求返回数据
6、 浏览器收到http响应然后处理数据,渲染页面,包括dom树,css,js等。

HTTPS 和 HTTP

HTTP+加密+认证+完整性保护 = HTTPS,HTTP协议采用明文传输信息,存在信息窃听、信息篡改和信息劫持的风险,而协议TLS/SSL具有身份验证、信息加密和完整性校验的功能,可以避免此类问题发生。
TLS/SSL全称安全传输层协议Transport Layer Security, 是介于TCP和HTTP之间的一层安全协议,不影响原有的TCP协议和HTTP协议,所以使用HTTPS基本上不需要对HTTP页面进行太多的改造。

http状态码

1xx 信息响应

  • 100 Continue,这个临时响应表明,迄今为止的所有内容都是可行的,客户端应该继续请求,如果已经完成,则忽略它。
  • 101 Switching Protocol,该代码是响应客户端的 Upgrade 标头发送的,并且指示服务器也正在切换的协议。
  • 102 Processing (WebDAV),此代码表示服务器已收到并正在处理该请求,但没有响应可用。
  • 103 Early Hints ,此状态代码主要用于与Link 链接头一起使用,以允许用户代理在服务器仍在准备响应时开始预加载资源。

2XX 成功响应(请求正常处理完毕)

  • 200 OK,表示从客户端发来的请求在服务器端被正确处理
  • 201 Created,该请求已成功,并因此创建了一个新的资源。这通常是在POST请求,或是某些PUT请求之后返回的响应。
  • 202 Accepted,请求已经接收到,但尚未执行。和异步请求和批处理有关。
  • 203 Non-Authoritative Information,此响应代码表示返回的元信息与原始服务器提供的信息并不完全相同,而是从本地或第三方副本中收集的。除该特定情况外,200 响应优先于此状态。
  • 204 No content,表示请求成功,但响应报文不含实体的主体部分(可能通过头部信息返回)
  • 205 Reset Content,请求成功但没有返回任何内容,要求请求者重置文档视图,通常用于重置表单。
  • 206 Partial Content,从客户端发送Range标头仅请求资源的一部分时,将使用此响应代码。
  • 207 Multi-Status (WebDAV)
  • 208 Multi-Status (WebDAV)
  • 226 IM Used (HTTP Delta encoding)

3XX 重定向(需要进行附加操作以完成请求)

  • 300 Multiple Choice 有多种可能响应可选。
  • 301 Moved Permanently,永久性重定向,表示资源已被分配了新的 URL
  • 302 Found,临时性重定向,应当继续访问此地址
  • 303 See Other,表示资源存在着另一个 URL,应使用 GET 方法定向获取资源
  • 304 Not Modified,表示服务器允许访问资源,但资源和之前没有改变
  • 305 Use Proxy,被请求的资源必须通过指定的代理才能被访问,只有原始服务器才能建立305响应
  • 307 Temporary Redirect,临时重定向,和302含义相同,区别是用户不能改变请求方法。
  • 308 Permanent Redirect,和301含义相同,区别也是用户不能改变请求方法。

4XX 客户端错误(服务器无法处理请求)

  • 400 Bad Request,请求报文存在语法错误
  • 401 Unauthorized,未认证,客户端必须对自己进行身份验证才能获得请求的响应
  • 403 Forbidden,表示对请求资源的访问被服务器拒绝(知道客户端身份,且其无权访问)
  • 404 Not Found,表示在服务器上没有找到请求的资源,通常是请求路径错误。
  • 405 Method Not Allowed 禁用的请求方法,一般遇到这种情况是服务器配置问题。
  • 406 Not Acceptable 没有找到符合条件的内容,但是路径是对的,比如request的Accept和response的Content-Type不匹配
  • 407 Proxy Authentication Required 类似于401,但需要由代理进行身份验证
  • 408 Request Timeout ... 429,431,451 诸多不常见错误,参见MDN

5XX 服务器错误(服务器处理请求出错)

  • 500 internal sever error,表示服务器端在执行请求时发生了错误
  • 501 Not Implemented,此请求方法不被服务器支持且无法被处理。
  • 502 bad getway,网关错误,比如没起nginx,nginx挂了一类的
  • 503 Service Unavailable,表明服务器暂时处于超负载或正在停机维护,无法处理请求
  • 504 Gateway Timeout,请求超时
  • 505 HTTP Version Not Supported 服务器不支持请求中所使用的HTTP协议版本
  • 506、507、508、510、511 更不常见,同上

请求方法

GET 方法,请求一个指定资源的表示形式. 使用GET的请求应该只被用于获取数据.
HEAD 方法,请求一个与GET请求的响应相同的响应,但没有响应体.
POST 方法,用于将实体提交到指定的资源,通常导致在服务器上的状态变化或副作用.
PUT 方法,用请求有效载荷替换目标资源的所有当前表示。
DELETE 方法,删除指定的资源。
CONNECT 方法,建立一个到由目标资源标识的服务器的隧道。
OPTIONS 方法,用于描述目标资源的通信选项。
TRACE 方法,沿着到目标资源的路径执行一个消息环回测试。
PATCH 方法,用于对资源应用部分修改。

请求超时

浏览器默认超时不同浏览器不同,和版本有影响,比如chrome 是4 分钟,safari 12分钟等。 http请求默认不会有超时,很多服务器会设置超时,如PHP服务默认的请求响应最长处理时间为30s,如果超过30s,将会返回504,nginx 也可以配置。axios npm 文档 支持配置参数设置timeout 并做拦截处理,抛错等。whatwg-fetch是不支持超时设置的,可以通过promise 改造等但是看来不好用,个人也没用过。

常见协议对应端口:

Telnet:tcp 23
ssh:tcp 22
ftp:tcp 21
http:tcp 80
https:tcp 443
dns:tcp 53,udp 53

跨域

同源策略

同源需要:(<img><link><script>三种标签不受限制)

协议相同
域名相同(子域名、主域名) 端口号相同

同源策略限制内容有:

Cookie、LocalStorage、IndexedDB 等存储性内容无法读取
DOM 无法获得
AJAX 请求不能发送

跨域方法:

非ajax

设置document.domain
通过url hash段传值
window.name
window.postMessage
...

ajax 跨域

  1. JSONP

利用 <script> 标签没有跨域限制的漏洞,网页可以得到从其他来源动态产生的 JSON 数据。JSONP请求一定需要对方的服务器做支持才可以。优点是兼容老式浏览器,但是只支持get而且不太安全,一般不用。

  1. CORS

CORS (跨域资源共享 Cross-origin resource sharing)需要浏览器和后端同时支持。IE 8 和 9 需要通过 XDomainRequest 来实现。
浏览器端会自动向请求头添加origin字段,表明当前请求来源。
服务器端需要设置响应头的Access-Control-Allow-Methods,Access-Control-Allow-Headers,Access-Control-Allow-Origin等字段,指定允许的方法,头部,源等信息。
请求分为简单请求和非简单请求,非简单请求会先进行一次OPTION方法进行预检,看是否允许当前跨域请求。

  1. node 中间层
  2. nginx 代理,详见下文
  3. webpack 配置 proxy,比如vue 的proxyTable or devServer.proxy

配置proxy 写法为:

devServer: {
	proxy: 'http://localhost:4000' // 会将任何未知请求 (没有匹配到静态文件的请求) 代理到http://localhost:4000
}
通常会用对象模式增加更多可配置项目
proxy: {
  '/api': { //匹配路由
    target: 'http://www.example.org', // 目标主机
    changeOrigin: true//默认保留主机头来源,设为true 会覆盖,跨域的时候需要如此设置
    ws: true,//代理websockets
    secure: false,// 如果需要支持https且证书无效的服务器
    pathRewrite: {
	    '^/api/old-path': '/api/new-path', // 重写路径,比如不希望传递/api
	    '^/api/remove/path': '/path' // 或者移除某基本路径
	  },
  },
  '/foo': {//对另一个路由的配置
    target: '<other_url>'
  }
}

CORS 简单请求和非简单请求:

简单请求

请求方法是以下三种方法之一:

  • HEAD
  • GET
  • POST

HTTP的请求头信息不超出以下几种字段:

  • Accept
  • Accept-Language
  • Content-Language
  • Content-Type (需要注意额外的限制)
  • DPR
  • Downlink
  • Save-Data
  • Viewport-Width
  • Width

Content-Type:只限于三个值

  • application/x-www-form-urlencoded
  • multipart/form-data
  • text/plain

请求中的任意XMLHttpRequestUpload 对象均没有注册任何事件监听器;XMLHttpRequestUpload 对象可以使用 XMLHttpRequest.upload 属性访问。

请求中没有使用 ReadableStream 对象。

后端的响应头信息:

  • Access-Control-Allow-Origin:必须。请求时Origin字段的值,或者*,表示接受任意域名的请求。
  • Access-Control-Allow-Credentials:可选,只能设为true,表示允许发送Cookie,这种情况下Access-Control-Allow-Origin 设置不能是*,如果不允许发送cookie,可删除此字段。
  • Access-Control-Expose-Headers:可选。CORS请求时,XMLHttpRequest对象的getResponseHeader()方法只能拿到6个基本字段:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。如果想拿到其他字段,就必须在Access-Control-Expose-Headers里面指定。
非简单请求

非简单请求是对服务器有特殊要求的请求,比如:

  • 请求方法是PUT或DELETE,(或使用了CONNECT、OPTIONS、TRACE、PATCH)
  • Content-Type字段的类型是application/json
  • 人为设置了其他首部字段。

非简单请求的CORS请求,会在正式通信之前,增加一次HTTP查询请求,称为"预检"请求(preflight)(OPTIONS)。

nginx 使用

nginx 常用功能:
反向代理,负载均衡,跨域配置,访问限制,资源处理等。[基本配置解说] (www.nginx.cn/76.html )
可通过homebrew 安装 brew install nginx,默认位于 /usr/local/etc/nginx,配置见nginx.conf,此配置最后 include servers/* ,在etc/nginx/servers文件夹下添加xxx.conf 文件内容会默认加到nginx.conf,可以直观的针对不同网站做不同配置。

常用命令:
sudo nginx -t //nginx 启动测试,检查配置是否正常,能否正常启动
sudo nginx //启动nginx
sudo nginx -s reload //重新启动
nginx -s stop //关闭

代理,反向代理

代理是在服务器和客户端之间假设的一层服务器,代理将接收客户端的请求并将它转发给服务器,然后将服务端的响应转发给客户端。

  1. 正向代理
    将访问服务器server的网页请求,代理到一个可以访问该网站的代理服务器proxy,代理服务器proxy把服务器server上的网页内容获取,转发给客户。客户端可以根据正向代理访问到它本身无法访问到的服务器资源
  2. 反向代理
    指代理服务器,客户端发送的请求,需要先发送到一个代理服务器proxy,通过proxy将请求发到和自己属于同一个LAN下的内部服务器(通常多台)。对服务端透明,对用户非透明,也就是加不加代理用户无感知,这样用户不能直接访问真正的内容服务器,增加安全性,可做负载均衡,健康检查,如果出问题将不会分配代理请求。

nginx 跨域配置

拦截local请求代理回server name 指定网址,浏览器使用 test.server.com 相当于 http://localhost:9997,这样请求就是以 test.server.com 域名请求接口,达到同源访问效果。

server {
    listen       80;
    server_name  test.server.com;
    location / {
            proxy_pass http://localhost:9997;
    }
}
# 如果https
server {
    listen       443 ssl;
    # https证书本地路径
    ssl_certificate xxxx;
     ssl_certificate_key xxxx;
     
     # 链接超时设置
     keepalive_timeout   70; 
     
    server_name  test.server.com;
    location / {
            proxy_pass http://localhost:9997;
    }
}

网站安全

网站安全问题有很多可能,总结的防御措施:

  • 永远不要相信来自客户端(用户)的输入,前后端都需要验证过滤转义用户输入,包括用户上传的文件需要做格式限制。输出检查转义。
  • 执行关键操作前必须验证用户身份,多阶段功能的每一步都要验证用户身份。
  • 对于直接对象引用,加密资源ID,以防止攻击者对ID进行枚举。本地存储与接口参数的敏感信息更要加密处理,包括数据库也是,不能把机密信息直接存放,加密或者 hash 掉密码和敏感的信息。
  • 不使用管理员权限的数据库连接,为每个应用使用单独的权限有限的数据库连接,不使用动态拼装 SQL,可以使用参数化的 SQL或者直接使用存储过程进行数据查询存取,保护数据安全。
  • 使用安全的第三方依赖。

个人上来说:注意密码复杂度,不同网站尽量不要重复,密码中尽量不要包括个人信息。谨慎点击各类可疑链接,不要连接可疑wifi等。防止劫持、撞库、钓鱼这类操作。

XSS

即 Cross Site Script,中译是跨站脚本攻击;其原本缩写是 CSS,但为了和层叠样式表(Cascading Style Sheet)有所区分,因而在安全领域叫做 XSS。
XSS 攻击是指攻击者在网站上注入恶意的客户端代码,通过恶意脚本对客户端网页进行篡改,从而在用户浏览网页时,对用户浏览器进行控制或者获取用户隐私数据的一种攻击方式。
攻击者对客户端网页注入的恶意脚本一般包括 JavaScript,有时也会包含 HTML 和 Flash。有很多种方式进行 XSS 攻击,但它们的共同点为:将一些隐私数据像 cookie、session 发送给攻击者,将受害者重定向到一个由攻击者控制的网站,在受害者的机器上进行一些恶意操作。

XSS攻击可以分为3类:
  1. 反射型(非持久型):诱使用户点击一个恶意链接,或者提交一个表单,或者进入一个恶意网站时,注入脚本进入被攻击者的网站 。比如通过覆盖透明层加恶意链接,伪装接近的正常链接短信诱骗点击等。
  2. 存储型(持久型):把用户输入的数据 "存储" 在服务器端,当浏览器请求数据时,脚本从服务器上传回并执行。这种 XSS 攻击具有很强的稳定性。
    比较常见的一个场景是攻击者在社区或论坛上写下一篇包含恶意 JavaScript 代码的文章或评论,文章或评论发表后,所有访问该文章或评论的用户,都会在他们的浏览器中执行这段恶意的 JavaScript 代码。
  3. 基于DOM:是指通过恶意脚本修改页面的 DOM 结构,是纯粹发生在客户端的攻击。
XSS的防范
  1. HttpOnly 防止劫取 Cookie
  2. 输入检查 用于对用户输入所包含的特殊字符或标签进行编码或过滤,这样脚本就转为文本不会执行
  3. 输出检查 一般来说,除富文本的输出外,在变量输出到 HTML 页面时,可以使用编码或转义的方式来防御 XSS 攻击。例如利用 sanitize-html 对输出内容进行有规则的过滤之后再输出到页面中,vue 和 react 本身是转义的。

CSRF

CSRF,即 Cross Site Request Forgery,中译是跨站请求伪造,是一种劫持受信任用户向服务器发送非预期请求的攻击方式。
比如借用户的cookie骗取服务器信任,给服务器发送请求,这种不能解析cookie内容也不能窃取改变返回数据。常见情况比如盗用用户信息给自己转账;伪装管理员用户增加管理员权限人员,以自由获得管理员权限;重置账号修改为自己信息等等。
防范:

  1. 使用验证码,在请求前加上用户交互,但是显然不能所有请求都这么做。
  2. 对http 头做Referer Check,可以检查请求是否来自合法的”源”。
  3. 在http请求中加入与cookie无关的token验证。当用户第一次进行登录的时候,客户端会通过用户名和密码去请求服务器登录,服务端在收到请求后会验证客户端传来的用户名和密码,如果验证通过,服务器就会签发一个token发给客户端,并且将token放到session或者报文中,客户端收到token后存储到本地,以后客户端只要每次请求服务器就要带上token,经过服务器验证通过后才会返回响应数据,否则报错。

DDOS 攻击

这也是比较知名的网络攻击,DDoS 攻击通过大量合法的请求,利用目标系统网络服务功能缺陷或者直接消耗其系统资源,使得该目标系统无法提供正常的服务。 防范需要提高网站性能与预警机制,及时做分流隔断等操作,就简介一下。