php - Laravel5 使用 fetch API 进行 ajax 的POST访问出现 TokenMismatchException

 Happy的紫璐 发布于 2022-11-29 20:35

最近在学习Laravel 5。

使用laravel new命令创建了一个新项目。

建了一个测试的 Controller,在/app/Http/Controllers下,完整代码:

 0
        ));
    }
    public function add() {
        return \Response::json(array(
            'status' => 0
        ));
    }
}

在路由配置(/routes/web.php)中添加:

Route::get('articles', 'ArticleController@list');
Route::post('articles', 'ArticleController@add');

用php artisan sereve启动服务器后,访问首页,在Chrome中打开控制台。

使用fetch API输入

  1. fetch('/articles'),GET方法,得到正常的结果

  2. fetch('/articles', { method: 'POST' }),得到 TokenMismatchException 的错误,Google了一下,说是跨域的问题。但我明显没有跨域;反证:如果有跨域,之前的 GET 方法也不可能会正常访问。

现在我有两个问题:

  1. 由于对后端开发不是很熟悉,我想请问一下,GET方法默认不跨域处理,POST方法默认跨域处理的原因是什么?后端开发框架为什么要默认采用这样的配置? 感觉没有理由啊。为什么不跨域的情况下POST方法也当作跨域处理了?不是应该在跨域的情况下才算跨域吗?

  2. Laravel怎么测试POST接口?我根据这篇文章介绍的,给POST的header加上了X-CSRF-TOKEN,照常在不跨域的情况下出现POST方法跨域的现象。

4 个回答
  • Laravel 会为每个活跃用户自动生成一个 CSRF "token" 。该 token 用来核实应用接收到的请求是通过身份验证的用户出于本意发送的,无论何时,当你需要定义一个 HTML 表单,你都应该在里面包含一个隐藏的 CSRF token ,只有这样,CSRF 保护中间件才会验证请求。所以应该是这样说:你的post请求都要带上csrf的token,附上文档https://laravel-china.org/doc...


    然后你提出的那两个问题,我这样回答:

    1. 跨域是因为你ajax发起请求域名或者端口和请求的api接口不同而导致浏览器不能识别的问题,解决跨域一般是使用jsonp的方式,但laravel有一个很好用的扩展包叫laravel-cros,你可以在github搜一下看看,所以跨域和get或post这两个请求方式没有关系,而且跨域的问题只会出现在浏览器上,而app上没有跨域问题

    2.关于接口测试推荐一款Chrome的插件叫:postman,很好用

    3.如果你想用laravel写接口的话,应该使用的路由是routes目录下的api.php,而不是web.php,新版本的laravel把这两个个路由分离出来更清晰了。所以还是建议多看一下文档哦

    2022-11-29 20:52 回答
  • 对于这个问题,我想说的是,这里 并不是为了解决跨域问题的,而且与跨域没有一毛钱的关系。TokenMismatchException 这个异常是在使用Laravel的 CSRF 中间件的时候,验证Token无效的情况下才会抛出的异常。

    public function handle($request, Closure $next)
    {
        if (
            $this->isReading($request) ||
            $this->runningUnitTests() ||
            $this->shouldPassThrough($request) ||
            $this->tokensMatch($request)
        ) {
            return $this->addCookieToResponse($request, $next($request));
        }
    
        throw new TokenMismatchException;
    }
    
    /**
     * Determine if the HTTP request uses a ‘read’ verb.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return bool
     */
    protected function isReading($request)
    {
        return in_array($request->method(), ['HEAD', 'GET', 'OPTIONS']);
    }
    

    为什么会采用这样的配置这个问题也就变成了为什么要采用这个中间件,这个可以百度一下什么是CSRF(跨站请求伪造攻击),在Laravel中就是为了防御这种攻击方式的。

    2022-11-29 20:52 回答
  • 跨域的处理的原理去了解了解,了解下为什么加token!

    2022-11-29 20:52 回答
  • 表单中添加{{csrf_field()}},好像是laravel自己设定的表单提交验证方式,具体也没研究过。

    2022-11-29 20:52 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有