带有 axios 的 API 请求总是未经 Laravel API 授权

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/49884611/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 17:38:56  来源:igfitidea点击:

API requests with axios always unauthorized with Laravel API

phplaravelapiaxios

提问by K3nzie

I'm working on a personal project using Laravel5.6 and Axioslibrary (standard Laravel 5.6package).

我正在使用Laravel5.6 和Axios库(标准 Laravel 5.6包)进行个人项目。

I need to send first GET then POST request using Laravel's API and axios' http requests, but I'm not using Passport or any library like that since it's an internal API serving only VueJS to obtain stuff from the database.

我需要先使用 Laravel 的 API 和 axios 的 http 请求发送 GET 然后 POST 请求,但我没有使用 Passport 或任何类似的库,因为它是一个内部 API,仅提供 VueJS 以从数据库中获取内容。

If I set my API routes using auth:apimiddleware, I always get unauthorized response, whichever is the request type, this is the error output :

如果我使用auth:api中间件设置我的 API 路由,我总是得到未经授权的响应,无论请求类型是什么,这是错误输出:

Error: Request failed with status code 401

错误:请求失败,状态码为 401

The message :

消息:

message: "Unauthenticated."

But, as I read in the documentation, axios headers are set inside laravel's bootstrap.jsto read the authorization token from meta tags (and the code is there) :

但是,正如我在文档中所读到的,axios 标头设置在 laravel 的内部bootstrap.js以从元标记读取授权令牌(并且代码在那里):

window.axios = require('axios');

window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';

// further down the file...
let token = document.head.querySelector('meta[name="csrf-token"]');

if (token) {
    window.axios.defaults.headers.common['X-CSRF-TOKEN'] = token.content;
} else {
    console.error('CSRF token not found: https://laravel.com/docs/csrf#csrf-x-csrf-token');
}

While, if needed, here's the http request code :

同时,如果需要,这里是 http 请求代码:

axios.post('/api/latest', formData)

So, why am I unauthenticated if those are set?

那么,如果设置了这些,为什么我未经身份验证?

I've tried removing the auth:apimiddleware and, of course, it's working:

我试过删除auth:api中间件,当然,它正在工作:

- Route::middleware('auth:api')->get('/latest', 'InternalApiController@latestEp');
+ Route::get('/latest', 'InternalApiController@latestEp');

What am I doing wrong?

我究竟做错了什么?

回答by Emile Bergeron

I'm not using Passort or any library like that since it's an internal API serving only VueJS to obtain stuff from the database.

我没有使用 Passort 或任何类似的库,因为它是一个内部 API,只为 VueJS 提供服务以从数据库中获取内容。

If the API is not stateless, meaning that the user is known to be logged in with a standard session cookie, then you can just use the default 'web'middleware for the API routes.

如果 API 不是无状态的,这意味着已知用户使用标准会话 cookie 登录,那么您可以只使用'web'API 路由的默认中间件。

In the default RouteServiceProvider, change the mapApiRoutesfunction to use the webmiddleware instead:

在 default 中RouteServiceProvider,将mapApiRoutes函数更改为使用web中间件:

protected function mapApiRoutes()
{
    Route::prefix('api')
        // ->middleware('api')
        ->middleware('web')
        ->namespace($this->namespace)
        ->group(base_path('routes/api.php'));
}


That being said, you should really put the API routes behind the default 'auth'middleware since they're not throttled by default.

话虽如此,您真的应该将 API 路由放在默认'auth'中间件后面,因为它们默认不受限制。

In the routes/api.phpfile:

routes/api.php文件中:

Route::group(['middleware' => 'auth'], function() {
    Route::get('/latest', 'InternalApiController@latest');
});

And if you want to ensure it's an AJAX request, you can create a simple middleware that checks that the request has the X-Requested-Withheader set to XMLHttpRequest.

如果您想确保它是一个 AJAX 请求,您可以创建一个简单的中间件来检查请求的X-Requested-With标头是否设置为XMLHttpRequest

class RequestIsAjax
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request $request
     * @param  \Closure $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        if (!$request->ajax()) {
            return redirect()->route('login.index');
        }

        return $next($request);
    }
}

And register it within the $routeMiddlewarearray inside the \App\Http\Kernelclass.

并将其注册在类内的$routeMiddleware数组中\App\Http\Kernel

protected $routeMiddleware = [
    'ajax' => \App\Http\Middleware\RequestIsAjax::class,

回答by Lassi Uosukainen

CSRF-token is not the same as an authorization token. Most likely you will manually need to add the authorization token, which is probably like this, depending on your method of authorization.

CSRF 令牌与授权令牌不同。您很可能需要手动添加授权令牌,这可能是这样的,具体取决于您的授权方法。