Vue 请求 Laravel 接口跨域问题

前言:项目使用了 vue 2 + laravel5.8 搭建。

原因:因为要使用 swoole,本机是windows(不支持swoole),遂使用docker搭建了一套dnmp环境并把接口服务移植到docker上。当vue请求接口时出现了跨域问题。

尝试:laravel接口部分已经使用了 mdez/cors 做中间件处理跨域请求,但是请求还是返回 405(Not Allowed)
Vue请求Laravel接口跨域问题

在百度搜索后,配置nginx如下:

Vue请求Laravel接口跨域问题

再次请求接口,返回如下:

Vue请求Laravel接口跨域问题

返回信息:

Vue请求Laravel接口跨域问题

问题:为什么已经返回 204 状态码,但是ajax请求依然报错跨域问题呢?

《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
最佳答案

@haostudy

前端 proxyTable 代理

proxyTable: {
    '/v1': {
      target: 'http://localhost',  // 目标接口域名
      changeOrigin: true,  // 是否跨域
    },
},

或者nginx反向代理

# origin 域名配置
location ~ ^/v1/ {
    #rewrite /v1/(.+)$ /$1 break;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_pass http://localhost; # 目标接口域名
}

ajax 请求

/v1/articles?page=1&limit=20 or http://localhost:8080/v1/articles?page=1&limit=20

这里需要用 Origin 域名请求,不要用目标域名去请求!

最后可以把 mdez/cors中间件去除了。

4年前 评论
hycreeze (楼主) 4年前
讨论数量: 18

可在 Nginx 对应的站点添加如下代码:

server {
    ...
    add_header Access-Control-Allow-Origin *;
    add_header Access-Control-Allow-Headers *;
    add_header Access-Control-Allow-Methods *;
    ...
}

仅供参考

4年前 评论
hycreeze (楼主) 4年前

在Nginx中应该是配置pass_proxy反向代理到你想要的地址吧,另一种方法是在框架里面设置请求头,像你上面添加的那些。
一个参考例子:https://github.com/a54552239/pearProjectAp...

4年前 评论
hycreeze (楼主) 4年前
xiebinbin 4年前
Sparkfly

跨域异步使用 cookie 时:

  1. Access-Control-Allow-Origin 不能配置 * , 需要配置具体域名;
  2. add_header Access-Control-Allow-Headers withCredentials always; 需要包含 withCredentials
4年前 评论

我按照 @Sparkfly 重新配置了 nginx 配置并且在Access-Control-Allow-Headers 处添加了 X-Xsrf-Token.但是问题依旧存在,依然提示

file

4年前 评论

附上我的 nginx 配置

file

4年前 评论
Sparkfly

@haostudy 页面 localhost , 你访问的是 localhost:8080,这个要和配置一致哦

4年前 评论
hycreeze (楼主) 4年前
Sparkfly (作者) 4年前
南城以南

所谓的跨域 是浏览器端的同源策略导致的。
如果仅仅是本地的 在chrome浏览器下可以直接给快捷方式设置:
--args --disable-web-security --user-data-dir
若线上跨域 需在排查时检查request的refer与response的refer是否一致。
同源策略相关可以查阅相关文档,简单来讲就是 协议/域名/端口必须在服务器可访问范围内。

4年前 评论

这是我用的中间件

<?php

namespace App\Http\Middleware;

use Closure;

class Cors
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        $response = $next($request);
        $origin = $request->server('HTTP_ORIGIN') ? $request->server('HTTP_ORIGIN') : '';
        $allow_origin = [
            'http://localhost:8000',
            'http://localhost:9530',
            'http://localhost:9529',
            'http://localhost:9531',
        ];
        $headers = [
            'Access-Control-Allow-Origin' => $origin,
            'Access-Control-Allow-Headers' => 'Origin, Content-Type, Cookie, X-CSRF-TOKEN, Accept, Authorization, X-XSRF-TOKEN',
            'Access-Control-Expose-Headers' => 'Authorization, authenticated',
            'Access-Control-Allow-Methods' => 'GET, POST, PATCH, PUT, OPTIONS',
            'Access-Control-Allow-Credentials' => 'true',
        ];
        $IlluminateResponse = 'Illuminate\Http\Response';
        $SymfonyResopnse = 'Symfony\Component\HttpFoundation\Response';
        // 因为 response 可能是两个不同的类 设置header 方式不一样
        if ($response instanceof $IlluminateResponse) {
            foreach ($headers as $key => $value) {
                $response->header($key, $value);
            }
            return $response;
        }

        if ($response instanceof $SymfonyResopnse) {
            foreach ($headers as $key => $value) {
                $response->headers->set($key, $value);
            }
            return $response;
        }
    }
}
4年前 评论
hycreeze (楼主) 4年前
Thresh-stone 2年前

直接做个反向代理不行吗

4年前 评论

可以直接在vue中做代理

4年前 评论
hycreeze (楼主) 4年前
风吹过有夏天的味道 (作者) 4年前

file 可以试试Nginx 代理

4年前 评论

@haostudy 刚查阅了一下文档,你可以试试 return 200. 毕竟 No Content 可能会导致 ajax 行为异常,当然只是猜测。手动滑稽

A 200 response SHOULD include any header fields that indicate optional features implemented by the server and applicable to that resource (e.g., Allow), possibly including extensions not defined by this specification. The response body, if any, SHOULD also include information about the communication options. The format for such a

4年前 评论

我之前也是出现过这个问题,5.8 需要全局注册中间价,可以查看之前我发的帖子

4年前 评论

@haostudy

前端 proxyTable 代理

proxyTable: {
    '/v1': {
      target: 'http://localhost',  // 目标接口域名
      changeOrigin: true,  // 是否跨域
    },
},

或者nginx反向代理

# origin 域名配置
location ~ ^/v1/ {
    #rewrite /v1/(.+)$ /$1 break;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_pass http://localhost; # 目标接口域名
}

ajax 请求

/v1/articles?page=1&limit=20 or http://localhost:8080/v1/articles?page=1&limit=20

这里需要用 Origin 域名请求,不要用目标域名去请求!

最后可以把 mdez/cors中间件去除了。

4年前 评论
hycreeze (楼主) 4年前

楼主 ,请问你是怎么解决的? 我出现了和你同样的问题

4年前 评论
hycreeze (楼主) 4年前

我在公司的开发环境用中间件可以正常访问,回到家里就不行,各种办法都试过了,还是不行,也不知道是哪里出问题了。

3年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!