跨域的产生和解决方法

本文详细介绍了前端跨域问题的原因和两种常见解决方案:JSONP和CORS。JSONP利用script标签的src属性实现跨域GET请求,而CORS通过在服务器设置Access-Control-Allow-*头部信息,允许浏览器发起跨域请求,支持更多请求方法和头信息。此外,还提到了非简单请求及nginx反向代理作为跨域的另一种策略。
摘要由CSDN通过智能技术生成

原因:跨域是由于浏览器存在同源策略,两个页面之间,如果协议、主机和端口中有任意一个不同,就会出现跨域问题

现象

  • Cookie、LocalStorage、IndexDB 无法读取;
  • DOM 和 JS 对象无法获取;
  • AJAX 请求无法发送

解决方案

  1. JSONP 跨域
    一些标签如 <script><img>没有跨域限制,利用src属性发送带有callback参数的GET请求,服务器将数据传入到callback函数中,返回给浏览器解析运行,从而在前端拿到数据。
    缺点:只能发起 GET 请求
// 前端代码
<script>
  let script = document.createElement('script');
  script.type = 'text/javascript';

  script.src = 'http://localhost:3000/login?name=lisa&callback=handle';
  document.head.appendChild(script);

  function handle(res){
    alert(res);  // 弹出name的值, 即lisa
  }
</script>
// node服务端代码
const Koa = require('koa');
const router = require('koa-router')();  //注意:引入的方式
const app = new Koa();
router.get('/login', function (ctx, next) {
  let request = ctx.request
  let query = request.query
  let name = query.name
  let fn = query.callback
  ctx.body =  fn + '(' + JSON.stringify(name) + ')'
})

app.use(router.routes()); //作用:启动路由
app.use(router.allowedMethods()); 
app.listen(3000,()=>{
console.log('starting at port 3000');
});
  1. CORS(跨域资源共享)
    它允许浏览器向跨域服务器发起 XMLHttpRequest 请求,从而避开 Ajax 的同源限制。
    CORS 请求需要浏览器和服务器都支持,所有浏览器都支持,IE 浏览器不能低于 IE10,可分为2种类型:简单请求和复杂请求
  • 简单请求: 满足以下2个条件即为简单请求
(1) 请求方法是以下三种方法之一:HEAD、GET、POST
(2)HTTP的头信息不超出以下几种字段:
  - Accept
  - Accept-Language
  - Content-Language
  - Last-Event-ID
  - Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain

对于简单请求,浏览器直接发出CORS请求。具体来说,就是在头信息之中,增加一个Origin字段,指明了本次请求的来源(协议+主机+端口)。服务器根据这个值来判断是否同意这次请求。
可在服务器对下面3个属性进行设置来实现 CORS 跨域
(1)Access-Control-Allow-Origin

该字段是必须的。它的值要么是请求时Origin字段的值,要么是一个*,表示接受任意域名的请求。

(2)Access-Control-Allow-Credentials

该字段可选。它的值是一个布尔值,表示是否允许发送Cookie。默认情况下,Cookie不包括在CORS请求之中。设为true,即表示服务器明确许可,Cookie可以包含在请求中,一起发给服务器。这个值也只能设为true,如果服务器不要浏览器发送Cookie,删除该字段即可。

(3)Access-Control-Expose-Headers

该字段可选。CORS请求时,XMLHttpRequest对象的getResponseHeader()方法只能拿到6个基本字段:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。如果想拿到其他字段,就必须在Access-Control-Expose-Headers里面指定。上面的例子指定,getResponseHeader(‘FooBar’)可以返回FooBar字段的值。

  • 非简单请求
  1. nginx 反向代理
#proxy服务器
server {
    listen       81;
    server_name  www.domain1.com;

    location / {
        proxy_pass   http://www.domain2.com:8080;  #反向代理
        proxy_cookie_domain www.domain2.com www.domain1.com; #修改cookie里域名
        index  index.html index.htm;

        # 当用webpack-dev-server等中间件代理接口访问nignx时,此时无浏览器参与,故没有同源限制,下面的跨域配置可不启用
        add_header Access-Control-Allow-Origin http://www.domain1.com;  #当前端只跨域不带cookie时,可为*
        add_header Access-Control-Allow-Credentials true;
    }
}
  1. vue.config.js 配置 proxy 代理
devServer: {
    // 首次打包成功后,自动打开浏览器
    open: true,
    // 在 http 协议中,如果端口号是 80,则可以被省略
    port: 8099,
    // 指定运行的主机地址
    host: '127.0.0.1',
    proxy: {
      '/api': {
        target: 'http://localhost:10003', // 目标的服务器接口
        changOrigin: true, // 允许跨域
        pathRewrite: {
          /* 重写路径,当我们在浏览器中看到请求的地址为:http://localhost:8080/api/core/getData/userInfo 时
                      实际上访问的地址是:http://localhost:8080/core/getData/userInfo,因为重写了 /api
                     */
          '^/api': ''
        }
      }
    }
  }

参考文章
9种常见的前端跨域解决方案(详解)
阮一峰 跨域资源共享 CORS 详解

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值