跨域

在本地开发时,接口地址一般为 127.0.0.1:8000

$php artisan serve
Starting Laravel development server: http://127.0.0.1:8000
[Thu Aug 25 10:10:42 2022] PHP 7.4.23 Development Server (http://127.0.0.1:8000) started

而前端地址看个人配置,我的如下:

vue.config.js
const port = process.env.port || process.env.npm_config_port || 9528 // dev port module.exports = { publicPath: '/', outputDir: 'dist', assetsDir: 'static', lintOnSave: process.env.NODE_ENV === 'development', productionSourceMap: false, devServer: { port: port, open: true, overlay: { warnings: false, errors: true }, before: require('./mock/mock-server.js') }, }
$ npm run dev

> trademark-crm-admin@4.4.0 dev
> vue-cli-service serve

 INFO  Starting development server...
98% after emitting CopyPlugin

 DONE  Compiled successfully in 4188ms                                                                                                                                                                      上午10:14:05


  App running at:
  - Local:   http://localhost:9528/ 
  - Network: http://192.168.1.13:9528/

  Note that the development build is not optimized.
  To create a production build, run npm run build.

这个时候直接配置接口地址来联调时就会出现跨域问题:

Access to XMLHttpRequest at 'http://127.0.0.1:8000/api/member/company/update' from origin 'http://localhost:9528' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: The 'Access-Control-Allow-Origin' header has a value 'http://localhost:9527' that is not equal to the supplied origin.

后端方案

本来准备自己写个中间件的,但是发现用的 Laravel8 默认引入了一个包 laravel-cors

"require": {
    "php": "^7.3|^8.0",
    "ext-pdo": "*",
    "barryvdh/laravel-ide-helper": "^2.12",
    "fruitcake/laravel-cors": "^2.0",
    "guzzlehttp/guzzle": "^7.0.1",
    "laravel/framework": "^8.75",
    "laravel/sanctum": "^2.11",
    "laravel/tinker": "^2.5",
    "predis/predis": "^2.0",
    "tymon/jwt-auth": "^1.0"
},

并且已经给你生成了一个配置文件,内容非常好理解,需要设置的头都给你做好了:

cors.php
return [ 'paths' => ['api/*'], 'allowed_methods' => ['*'], 'allowed_origins' => ['http://localhost:9528'], 'allowed_origins_patterns' => [], 'allowed_headers' => ['*'], 'exposed_headers' => [], 'max_age' => 0, 'supports_credentials' => true, ];

把前端地址加进去后就完事了

前端方案

如果是纯前端解决跨域问题,可以用 webpack 的 devServer.proxy

proxy: {
  "/api": "http://localhost:8000"
}

生产环境就要 Nginx 反向代理,上文中已经给过配置:

# 前端
server{
    location /api {
        proxy_pass http://localhost:81;
    }
}
# 后端
server{
   listen 81;
}

不是所有的跨域情况下的请求都需要先发送一个 options 请求的。比如一些简单请求是不需要的比如 get 请求,但也不是所有的 get 请求都不会发 options

它的 Content-Type 的值仅限于下列三者之一:

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

并且没有设置如下的 自定义 Header

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

而且还要注意一点,也不是只有 XMLHttpRequest 或者 fetch 请求才会有跨域问题,使用 drawImage 的 Canvas、Web 字体 、CSSDOM 也都是有这问题的

想了解更多可以阅读 MDN 跨源资源共享(CORS)

苍龙