PHP跨域

跨域,后台跨域,php

一、为什么会出现跨域问题

出于浏览器的同源策略限制,跨域问题一般是浏览器调用接口前端域名和后台域名对不上才产生。

二、什么是跨域

当一个请求url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域

三、怎么解决跨域

首先了解一下这些请求头有什么含义

Access-Control-Allow-Origin 指定允许其他域名访问,一般用法(*,指定域,动态设置)
Access-Control-Allow-Credentials:true 是否允许后续请求携带认证信息(cookies),该值只能是true,否则不返回
Access-Control-Allow-Methods 指定那种类型的请求能跨域(一般设置GET, POST,按照业务需求设置)
Access-Control-Allow-Headers 规定设置那些请求头能跨域(一般设置验证给Authorization那个请头过就行了)

可以用nginx伪静态添加每个进来添加跨域请求头

text
location / {  
    add_header Access-Control-Allow-Origin *;
    add_header Access-Control-Allow-Methods 'GET, POST, PATCH, PUT, DELETE, OPTIONS;
    add_header Access-Control-Allow-Headers 'Authorization,DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-T 
    ype';
     add_header Access-Control-Allow-Credentials true
}

不过多项目的服务器不建议用nginx解决跨域问题通用服务器迁移和不要用到的跨域项目加上了多余的强求头不美观

原生php

可以在入口文件哪里或者要用到跨域的地方加上

text
header('Access-Control-Allow-Credentials:true');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods:GET, POST, PATCH, PUT, DELETE, OPTIONS');
header('Access-Control-Allow-Headers: Authorization,Token,Content-Type, If-Match, If-Modified-Since, If-None-Match, If-Unmodified-Since, X-CSRF-TOKEN, X-Requested-With');

基本可以实现跨域

ThinkPhp6框架

这里用到中间件来实现跨域,官网那个跨域不是很支持自定义不好自己创建一个CrossDomain.php中间件更好跨域

注意:

  1. 这里用了中间件有时项目报接口404会报CORS报错的,请求没到中间件直接截断了可能。
  2. 最好不要用exit() die() 那些强制截断也是不到中间件的,应该框架级别的截断。
  3. 觉得麻烦可以直接在pubilc/index.php那个入口文件加上面原生php跨域问题可以直接解决。
text
<?php

namespace app\middleware;

use think\Config;

class CrossDomain
{
    protected $header = [
        'Access-Control-Allow-Credentials' => 'true',
        'Access-Control-Allow-Methods' => 'GET, POST, PATCH, PUT, DELETE, OPTIONS',
        'Access-Control-Allow-Headers' => 'Authorization,Token,Content-Type, If-Match, If-Modified-Since, If-None-Match, If-Unmodified-Since, X-CSRF-TOKEN, X-Requested-With',
        'Access-Control-Allow-Origin' => '*'
    ];

    public function __construct(Config $config)
    {
        $this->cookieDomain = $config->get('cookie.domain', '');
    }

    public function handle($request, \Closure $next)
    {
        $response = $next($request);
        $origin = $request->header('Origin', '');

        //OPTIONS请求返回204请求
        if ($request->method(true) === 'OPTIONS') {
            $response->code(204);
        }

        $header = !empty($header) ? array_merge($this->header, $header) : $this->header;
        if (!isset($header['Access-Control-Allow-Origin'])) {
            $origin = $request->header('origin');

            if ($origin && ('' == $this->cookieDomain || strpos($origin, $this->cookieDomain))) {
                $header['Access-Control-Allow-Origin'] = $origin;
            } else {
                $header['Access-Control-Allow-Origin'] = '*';
            }
        }
        $response->header($header);


        return $response;
    }


}