博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
前后端都需要知道的跨域
阅读量:5844 次
发布时间:2019-06-18

本文共 4804 字,大约阅读时间需要 16 分钟。

what 跨域

  • 跨域(跨域 HTTP 请求)就是前端在访问接口的时候,与访问的接口的 协议、域名、端口号 不是同一个,就会有跨域问题,这里产生跨域问题的原因是 XmlHttpRequest同源策略 ,也就是禁止使用XHR对象向不同源的服务器地址发起HTTP请求。

why 跨域

  • AJAX同源策略主要用来防止CSRF攻击。如果没有AJAX同源策略,相当危险,因为我们发起的每一次HTTP请求都会带上请求地址对应的cookie。

请求的种类

1、简单请求

请求方法 header
HEAD Accept、Accept-Language、Content-Language、Last-Event-ID、Content-Type(只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain)
GET
POST

2、非简单请求

除了上面的请求方法外的其他方法 delete、put 两个,还有携带其他自定义的请求头 即为非简单请求。

浏览器处理简单请求

1、基本流程

先增加一个 Origin 字段,这个是直接拿的请求发起页面的http协议和域名还有端口

服务端需要支持我们这个origin跨域请求,各个版本的跨域设置看文章底部。

{    
"Access-Control-Allow-Origin": string
"Access-Control-Allow-Headers": String
"Access-Control-Allow-Methods": String
"Access-Control-Allow-Credentials": Boolean
"Access-Control-Max-Age": Number}复制代码

浏览器处理复杂请求

  • 复杂请求在跨域请求的时候浏览器会发送一个预检请求,method 为 option,服务端需要首先通过验证这个预检请求,给这个请求返回 200 ,此时的 header 和 method 必须和 access-control-allow 中设置的保持一致。浏览器收到 option 响应,确认设置的 method 和 header 对上了,认为预检通过了,就开始正式的发送这个请求。
// 一次option预请求:authority: i-863.kaixindou.net:method: OPTIONS:path: /gameInfo/fetchPkWinStreakShareInfo?uid=101001638&streakWin=3:scheme: httpsaccept: */*accept-encoding: gzip, deflate, braccept-language: zh-CN,zh;q=0.9access-control-request-headers: x-lang,x-ostypeaccess-control-request-method: GETorigin: https://www.kaixindou.netuser-agent: Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Mobile Safari/537.36复制代码
  • 预检请求的允许通过,此时预检请求返回 200 在 preview 中看到 200 或者一个空页面
access-control-allow-credentials: trueaccess-control-allow-headers: x-lang, x-ostypeaccess-control-allow-methods: OPTIONS,GET,POSTaccess-control-allow-origin: https://www.kaixindou.netcontent-length: 0date: Wed, 15 Aug 2018 13:09:38 GMTserver: nginxstatus: 200vary: Access-Control-Request-Methodvary: Originvary: Access-Control-Request-Headers复制代码
  • 预检请求不允许通过,预检请求同样返回 200 ,在 preview 中看到 nothing to preview,response没有返回 access-control-allow 相关字段
    • header 报错
    // console 的报错Request header field xxxx is not allowed by Access-Control-Allow-Headers in preflight response.复制代码
    // 网络请求的 responseContent-Type: application/json; charset=utf-8复制代码
    • origin 报错
    // console 的报错Origin xxxxxxxxxx is not allowed by Access-Control-Allow-Origin.复制代码
    // 网络请求的 responseContent-Type: application/json; charset=utf-8复制代码

怎么避免这个预请求

  • 我们一般开发,会涉及到预请求的无非就是设置了其他的 header,方法我们也只是用到 get 和 post
  1. 让服务端缓存我们的预请求
// 让服务器设置下面这个头,在多次请求的时候可以避免二次预检Access-Control-Max-Age: ms复制代码
  1. 和服务端协商,设置的 header 使用 Last-Event-ID 等浏览器预置的 header,从根本上避免 option 的预请求

开发中遇到的问题

  • jq的 ajax 的携带 header 好坑,怎么都带不上去,建议使用
    // axios比较烦的 get 请求和 post 请求的参数位不一样,建议使用自己简单封装下Axios({  url: url[region] + '/wemeet/set_img_status',  method: 'post',  data: data,// post 使用  param: data,// get 使用  headers: { 'X-Auth-Token': encodeURIComponent(token) }}).then(rsp => rsp.data).catch(err => {  console.log(err.message)})复制代码
  • 封装过的
    export const axios = (url, type = 'GET', data = {}) => {  if (typeof url === 'object') {    return Axios(url)  }  if (typeof type === 'object') {    data = type    type = 'GET'  }  const axiosData = {    withCredentials: true,    method: type,    url  }  if (type === 'GET') {    axiosData.params = data  }  if (type === 'POST') {    axiosData.data = data  }  axiosData.headers = { header: '12321' }  return Axios(`${url}`, axiosData).then(rsp => {    console.log(`${url}`, rsp.data)    return rsp.data  }).catch(e => {    alert(e.message)  })}复制代码

附录

  • node express 跨域设置
// 使用express中间件const whiteList = [ xx.com ]app.use('*', (req, res, next) => {	let origin = req.headers.origin	let allowOrigin = 'http://fe.xx.com'	origin && whiteList.forEach(v => {		if (origin.indexOf(v) !== -1) {			allowOrigin = origin		}	})	res.header("Access-Control-Allow-Origin", allowOrigin)	res.header("Access-Control-Allow-Headers", "Content-Type, Authorization, X-Requested-With")	res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS")    res.header("Access-Control-Allow-Credentials", true)    res.header("Access-Control-Max-Age", 1728000)	res.header("X-Powered-By", '3.2.1')	if (req.method == 'OPTIONS') {	  res.send(200)	} else {	  next()	}});复制代码
  • go 跨域设置
func allowCrossOrigin(rw http.ResponseWriter, req *http.Request) {	if strings.ContainsAny(req.Header.Get("Origin"), "yy.com") {		rw.Header().Set("Access-Control-Allow-Origin", req.Header.Get("Origin"))		rw.Header().Set("Access-Control-Allow-Method", "PUT,OPTIONS,POST,GET")		rw.Header().Set("Access-Control-Allow-Credentials", "true")		rw.Header().Set("Access-Control-Allow-Headers", "Content-Type, X-Auth-Token")	}}func HttpGetImgList(rw http.ResponseWriter, req *http.Request) {    if req.Method == http.MethodOptions {    	allowCrossOrigin(rw, req)    	com_http.SendCommonResp(rw, req.URL.Query().Get("callback"), 0, "r u ok", "")    	return    }}复制代码
参考链接

转载地址:http://bshcx.baihongyu.com/

你可能感兴趣的文章
《跟菜鸟学Cisco UC部署实战》-第 0 章 宣传-课件(一共12章,免费)
查看>>
一道面试问题学生们的多种解答汇总
查看>>
Swift项目开发实战-基于分层架构的多版本iPhone计算器-直播公开课
查看>>
[How-to]如何查看Hyper-V实时迁移所需的时间
查看>>
域控服务器上安装Lync标准版记录
查看>>
一次沟通不佳造成的深刻教训
查看>>
AWS System Manger 批量操作EC2 实例
查看>>
数据结构—顺序表的插入算法
查看>>
Azure Stack-1807 版本 配置10分钟、自动部署6小时-我的ASDK第7次实践
查看>>
Ceph配置参数(一)
查看>>
MongoDB 3.2 版本说明(Release Notes for MongoDB 3.2)
查看>>
SCOM 2007 R2安装部署各组件支持的操作系统详细列表
查看>>
华三H3C官方模拟器HCL从入门到精通视频教程(9课时)
查看>>
笔记:AIX系统/var/adm/wtmp大文件处理
查看>>
Dynamic ARP Inspection(DAI)工作原理及测试
查看>>
mysql语法总结和练习
查看>>
tomcat性能优化
查看>>
OpenCV基于傅里叶变换进行文本的旋转校正
查看>>
谁分配、谁释放的原则需要goto
查看>>
C#中字符串的内存分配与驻留池
查看>>