Yii2+vue跨域问题解决

简介

最近公司想提升档次,就拿我们的PC页面开刀(我觉得YII自带的views蛮好的啊,前端插件也很多),没办法,
只能改了,遇到了一个坑就是跨域.

跨域和同源

跨域:

就是跨域名,跨端口,跨协议

     例如:如果有两个服务器,服务器A和服务器B,服务器A上存储了php数据,script,甚至是css这些文件,而你在服务器B上只写了html,然后你所在的服务器B上动态创建script,css,php数据(使用ajax请求),向服务器A上请求你想要的script,css,php数请求据(使用ajax)这些文件,请求这些文件后,你再在服务器B上运行你的html,虽然你的地址是在服务器B上,但是你还是可以运行效果与在服务器A上运行的效果是一样的,这样就是跨域名,跨端口,跨协议,实现了跨域。

  简单来说,就是你请求的文件,只要含有“src”,“href”这些属性,你就能在其他服务器上,请求你所需要的文件,然后在自己的服务器上运行,就实现了跨域(跨域名,跨端口,跨协议)。

原生的动态请求script文件 

  var _script = document.createElement("script");
  _script.src="http://10.9.156.108/html5/Ajax/api/sendMessage.php?user="+_user+"message="+_message;
  _script.type="text/javascript";

jQuery跨域请求script文件

$(document).ready(function(){
  //getJSON 后面带参数,如果不带参数默认不跨域 ,带了参数跨域

  //跨域优先
  $.<link rel="icon" href="../img/favicon.ico" type="image/x-icon">("http://10.9.156.108/HTML5/lesson24/test.js?callback=?",[data],function(){});

  //跨域  有getJSON 和 jsonp 两种方式(当然,我们现在说说别的)
  $.get("http://10.9.156.108/HTML5/lesson24/test.js=",null,function(){},"jsonp");
   
}); 

同源:

就是同域名,同端口,同协议

例如:如果你有一个服务器A,你所需要的script,css,php文件都在服务器A,你写的html也在服务器A上,然后运行,出现了效果,如果你想在另一台电脑上运行你的项目(注意另一台电脑无论有没有开启服务器,效果还是会显示出来的),只要把你写在服务器A上的协议,域名,端口以及你的项目名称复制下来,在另一台电脑上运行,同样会出现相同的效果,这就实现了同源。

Yii2 + vue.js

yii2写接口(无需验证),vue写前端

1.apache服务器:
啥都不要配置,vue那个写个代理配置就行

2.nginx服务器
加个几行header配置:
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Headers X-Requested-With;
add_header Access-Control-Allow-Methods GET,POST,OPTIONS;

yii2+restful+token验证,vue前端

这个还是比较重要的,流着泪填坑......
  • 这里我们的前端同学们就可以喝喝茶,当个吃瓜群众了.
  • 当页面上出现类似的报错,恭喜你,请跟我来.

跨域
跨域

  • 经过一系列的挣扎,最后总结如下(借鉴了一名无名同学)
1.我们这里首先把nginx配置给注释掉

2.配置响应头 项目config目录main.php中
'response' => [
      'class' => 'yii\web\Response',
      'on beforeSend' => function ($event) {
          $response = $event->sender;
          $response->format = yii\web\Response::FORMAT_JSON;
          $code = $response->getStatusCode();
          if ($code == 401) {
              $response->data = [
                  'code' => 401,
                  'msg' => 'token 验证失败^-^.'
              ];
          }
          $msg = !empty($response->data['msg']) ? $response->data['msg'] : yii\web\Response::$httpStatuses[$code];
          $code = !empty($response->data['code']) ? $response->data['code'] : $code;
          $data = !empty($response->data['data']) ? $response->data['data'] : [];
          ##### 从这里开始 #####
          $response->headers->set('Access-Control-Allow-Origin', '*');
          $response->headers->set('Access-Control-Allow-Methods', 'GET,POST,OPTIONS');
          $response->headers->set('Access-Control-Request-Headers', 'Origin,X-Requested-With, Content-Type, Accept, Token');
          //这两个很重要,token在header必须要这样设置
          $response->headers->set('Access-Control-Expose-Headers', 'token');
          $response->headers->set('Access-Control-Allow-Headers', 'token');
          //加这个是为了骗过OPTIONS请求
          if (Yii::$app->request->getMethod() == 'OPTIONS') {
              $response->setStatusCode(200);
          }

          $response->data = renderJSON($msg, $data, $code);
      },
  ],

3. 在自定义的基础控制器:
public function behaviors()
{
    #这个是我需要用token验证
    $behaviors = ArrayHelper::merge(parent::behaviors(), [
        'authenticator' => [
            'class' => QueryParamAuth::className(),
            'tokenParam' => 'token',
        ]
    ]);
    #这是将验证器赋值给变量,删除验证
    $auth = $behaviors['authenticator'];
    unset($behaviors['authenticator']);
    #这里是跨域设置
    $behaviors['corsFilter'] = [
        'class' => \yii\filters\Cors::className(),
    ];
    #当跳过跨域之后,要对请求的URL进行token验证
    $behaviors['authenticator'] = $auth;
    $behaviors['authenticator']['except'] = ['options'];
    return $behaviors;
}

跨域

总结

面对这些问题,尽量在后端解决,公司里的前端小伙伴太少了,好好珍惜...
Leo wechat
欢迎您扫一扫上面的二维码,成为好友吧!
坚持原创技术分享,您的支持将鼓励我继续创作!