前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >[CodeIgniter4]前后端分离跨域问题

[CodeIgniter4]前后端分离跨域问题

原创
作者头像
逝水经年
发布2022-03-03 12:45:59
2.5K0
发布2022-03-03 12:45:59
举报
文章被收录于专栏:数据可视化

一、背景

最近在弄毕业设计啦,采用CodeIgniter4+Vue3来做的,前后端分离项目,首先便是跨域问题。一顿搜索无果后,自己折腾了一个解决方案,希望能帮助到看到这篇文章的你。

二、跨域问题

由于浏览器的 同源策略 限制,使用前后端分离的模式下,前端和后端的域名一般都不是一样的,在我的项目中,前端是使用二级域名,而后端是使用三级域名,此时前后端就不同源了,就产生了跨域问题。

同源即两个页面具有相同的协议(protocol),主机(host)和端口号(port)

下表即我目前遇到的情况

域名

域名级别

框架

前端

example.com

二级域名

Vue3

后端

api.example.com

三级域名

CodeIgniter4

三、解决方法

1.问题

在前端往后端发送请求时,控制台会输出跨域报错,无法拿到数据。此时控制台会显示Access-Control-Allow-Origin不包含当前发送请求页面的相关提示。

2.解决思路

最常见的方法便是把响应头设置为

Access-Control-Allow-Origin: *

但这样每个接口都要设置一遍,会比较麻烦。

此时我们需要用到CodeIgniter4中的控制器过滤器里面的 前置过滤器

前置过滤器的官方文档

然后在前置过滤器中完成响应头的设定即可。

3.实现

(1)在app下找到Filters文件夹,如果没有,请先创建;

(2)在Filters文件夹下创建CorsFilter.php文件。

(3)写入以下代码

代码语言:php
复制
<?php

namespace App\Filters;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
use CodeIgniter\Filters\FilterInterface;

class CorsFilter implements FilterInterface
{
    // 前置过滤器
    public function before(RequestInterface $request, $arguments = null)
    {
        $response = service('response');
        $response->setHeader('Access-Control-Allow-Origin', '*');
    }

    //--------------------------------------------------------------------
    // 后置过滤器
    public function after(RequestInterface $request, ResponseInterface $response, $arguments = null)
    {
        // Do something here

    }
}

(4)在app/Config/Filters.php中配置我们刚刚创建的过滤器。大功告成!

代码语言:php
复制
// ----上面代码省略,无需修改----

public $aliases = [
        'csrf'     => CSRF::class,
        'toolbar'  => DebugToolbar::class,
        'honeypot' => Honeypot::class,
        'cors' => CorsFilter::class
    ];

public $globals = [
    'before' => [
        // 配置生效页面,except里面配置的时不生效页面
        'cors'=> ['except' => ['/yourPage1', '/yourPage2/detail']]
    ],
    'after' => [
    ],
];

// ----下面代码省略,无需修改----

4.自定义请求头(无此需求可跳过)

由于我的项目需要自定义请求头,这时候又得另外处理一下。

使用 自定义请求头 时,前端(客户端浏览器)会先发出一个OPTIONS请求,来判断是否可用,如果这时候没有进行设置的话,同样也是无法完成跨域的。

在上面的基础上加入以下代码

代码语言:php
复制
// 允许各种方法
$response->setHeader('Access-Control-Allow-Method', '*');
// 允许User-Token请求头(如果你是其他的自定义头,请更改)
$response->setHeader('Access-Control-Allow-Headers', 'User-Token');
// 判断请求的方法是否为OPTIONS,如果为OPTIONS,则返回200OK,表示服务器可以接受该方法
if($request->getMethod(FALSE)=='options'){
    return $response->setStatusCode(200,'OK');
}

加入处理自定义请求头的完整控制器过滤器代码

代码语言:php
复制
<?php

namespace App\Filters;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
use CodeIgniter\Filters\FilterInterface;

class CorsFilter implements FilterInterface
{
    // 前置过滤器
    public function before(RequestInterface $request, $arguments = null)
    {
        $response = service('response');
        $response->setHeader('Access-Control-Allow-Origin', '*');
        $response->setHeader('Access-Control-Allow-Method', '*');
        $response->setHeader('Access-Control-Allow-Headers', 'User-Token');

        if($request->getMethod(FALSE)=='options'){
            return $response->setStatusCode(200,'OK');
        }
    }

    //--------------------------------------------------------------------
    // 后置过滤器
    public function after(RequestInterface $request, ResponseInterface $response, $arguments = null)
    {
        // Do something here

    }
}

四、注意事项

在创建过滤器文件中,不能删除后置过滤器

错误代码

代码语言:php
复制
<?php
// 错误代码示例!!!!
namespace App\Filters;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
use CodeIgniter\Filters\FilterInterface;

class CorsFilter implements FilterInterface
{
    // 前置过滤器
    public function before(RequestInterface $request, $arguments = null)
    {
        $response = service('response');
        $response->setHeader('Access-Control-Allow-Origin', '*');
    }
}
// 错误代码示例!!!!

正确代码

代码语言:php
复制
<?php

namespace App\Filters;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
use CodeIgniter\Filters\FilterInterface;

class CorsFilter implements FilterInterface
{
    // 前置过滤器
    public function before(RequestInterface $request, $arguments = null)
    {
        $response = service('response');
        $response->setHeader('Access-Control-Allow-Origin', '*');
    }

    //--------------------------------------------------------------------
    // 后置过滤器
    public function after(RequestInterface $request, ResponseInterface $response, $arguments = null)
    {
        // Do something here

    }
}

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、背景
  • 二、跨域问题
  • 三、解决方法
    • 1.问题
      • 2.解决思路
        • 3.实现
          • 4.自定义请求头(无此需求可跳过)
          • 四、注意事项
            • 在创建过滤器文件中,不能删除后置过滤器
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档