网站首页 » PHP » Php 复杂请求 options 和 post , 跨域问题

Php 复杂请求 options 和 post , 跨域问题

July 17, 2020 PHP

options 请求的出现和作用我就不多叙述了,可以上网查到很多相关的资料, 我主要想谈一下options 到底请求的是你post请求的地址吗?

答案是错误,Options请求并不是跟你POST请求的同一个地址, 下面请看原因及我个人的测试。

最近在使用thinkcmf做接口开发, thinkcmf 内置有接口基类 apiportalcontrollerRestBaseController

文件位置在 vendor/thinkcmf/cmf/src/controller/RestBaseController.php

在此文件中,有在header中的参数 : XX-Token,XX-Api-Version,XX-Wxapp-AppId

在success 和 error 方法中设置了允许跨域, 并在header中带有的参数

success方法:

  protected function success($msg = '', $data = '', array $header = [])
    {
        $code   = 1;
        $result = [
            'code' => $code,
            'msg'  => $msg,
            'data' => $data,
        ];

        $type                                   = $this->getResponseType();
        $header['Access-Control-Allow-Origin']  = '*';
        $header['Access-Control-Allow-Headers'] = 'X-Requested-With,Content-Type,XX-Device-Type,XX-Token,XX-Api-Version,XX-Wxapp-AppId';
        $header['Access-Control-Allow-Methods'] = 'GET,POST,PATCH,PUT,DELETE,OPTIONS';
        $response                               = Response::create($result, $type)->header($header);
        throw new HttpResponseException($response);
    }

error 方法:

protected function error($msg = '', $data = '', array $header = [])
    {
        $code = 0;
        if (is_array($msg)) {
            $code = $msg['code'];
            $msg  = $msg['msg'];
        }
        $result = [
            'code' => $code,
            'msg'  => $msg,
            'data' => $data,
        ];

        $type                                   = $this->getResponseType();
        $header['Access-Control-Allow-Origin']  = '*';
        $header['Access-Control-Allow-Headers'] = 'X-Requested-With,Content-Type,XX-Device-Type,XX-Token,XX-Api-Version,XX-Wxapp-AppId';
        $header['Access-Control-Allow-Methods'] = 'GET,POST,PATCH,PUT,DELETE,OPTIONS';
        $response                               = Response::create($result, $type)->header($header);
        throw new HttpResponseException($response);
    }

我自己重写了基类,不使用自带的基类。
2020-07-11T09:57:54.png

在基类中,我也将header中携带的认证参数做了更改, success方法如下。

 protected function success($msg = '', $data = [], array $header = [])
    {
        $code   = 1;
        $result = [
            'code' => $code,
            'msg'  => $msg,
            'data' => $data,
        ];

        $type                                   = $this->getResponseType();
        $header['Access-Control-Allow-Origin']  = '*';
        $header['Access-Control-Allow-Headers'] = 'X-Requested-With,Content-Type,read-Device-Type,read-Token';
        $header['Access-Control-Allow-Methods'] = 'GET,POST,PATCH,PUT,DELETE,OPTIONS';
        $response                               = Response::create($result, $type)->header($header);
        throw new HttpResponseException($response);
    }

此时,问题就来了,在使用post 访问接口的时候一直提示跨域,
页面代码

<html>
<head></head>
<body>


<script src="https://www.showdoc.cc/static/jquery.min.js"></script>
<script>
    $(function(){

        $.ajax(
            {
                url:'http://wxofficial.kevink.club/api/frontend/public/auth',
                type:'post',
                dateType:'json',
                headers:{'Content-Type':'application/json;charset=utf8','read-Device-Type':'wxweb', 'read-Token': '95a426f84c28a4b0d91defc8ddd025c2'},
                success:function(data){
                    //console.log("sucess");
                    console.log(data)
                },
                error:function(data){console.log("error");}
            }
        );

    })
</script>
</body>
</html>

返回结果:
2020-07-11T10:03:42.png

注意红框标志, 请求的Access-Control-Allow-Headers 并不是我设置在自己基类中的值。 我设置的是: X-Requested-With,Content-Type,read-Device-Type,read-Token

2020-07-11T10:01:06.png

由此可见,options 请求肯定与post请求,访问的接口不同,如果相同,那么不会出现跨区情况。下面我就来找一下options 请求到底去访问了哪。

如果我访问thinkcmf 框架的api, 会出现以下提示
2020-07-11T10:05:28.png

那就来找找这个地址访问到了哪,最终定位到:vendor/thinkcmf/cmf-api/src/home/controller/IndexController.php

<?php
// +----------------------------------------------------------------------
// | ThinkCMF [ WE CAN DO IT MORE SIMPLE ]
// +----------------------------------------------------------------------
// | Copyright (c) 2013-2017 http://www.thinkcmf.com All rights reserved.
// +----------------------------------------------------------------------
// | Author: Dean <zxxjjforever@163.com>
// +----------------------------------------------------------------------
namespace api\home\controller;

use cmf\controller\RestBaseController;

class IndexController extends RestBaseController
{
    // api 首页
    public function index()
    {
        $this->success("恭喜您,API访问成功!", [
            'version' => '1.1.0',
            'doc'     => 'http://www.thinkcmf.com/cmf5api.html'
        ]);
    }

}

那我们就重写一下home模块, 在api 文件夹下创建home模块, 写一个IndexController 控制器接口,继承我自己的基类文件 RestBaseController.
2020-07-11T10:08:15.png

再去访问下刚才提示跨域的接口, 发现在header 中还是有 XX-Token, XX-DeviceType.
说明还是没有解决到问题。

最终结论
options请求访问的接口地址跟post访问的接口地址不是同一个地址,如果是同一个地址,header中不应该出现 XX-Token 而是 read-Token.

添加新评论