使用 axios 的 API 请求总是未经 Laravel API 授权

Posted

技术标签:

【中文标题】使用 axios 的 API 请求总是未经 Laravel API 授权【英文标题】:API requests with axios always unauthorized with Laravel API 【发布时间】:2018-09-27 19:18:44 【问题描述】:

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

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

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

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

消息:

message: "Unauthenticated."

但是,正如我在文档中所读到的,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');

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

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

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

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

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

我做错了什么?

【问题讨论】:

【参考方案1】:

使用 Laravel 8,我在尝试从后端 api 请求某些内容时收到 401 错误。遵循接受的答案让我很接近,但它仍然没有用。我相信这是因为我在子域上的仪表板为users.mydomain.tld,而我使用 Axios 的位置在主域上为mydomain.tld/some/path。问题是会话 cookie 的路径。重新配置时,您需要清除所有 cookie(开发工具栏)。然后在您进行更改后像往常一样重新登录。否则,cookie 将被弄乱,您将无法看到它已修复,或者在您清除它们之前您将无法登录。

我恢复了我所做的所有更改(遵循公认的答案)并确定 SESSION_DOMAIN 环境变量是关键因素,至少当涉及到主要用户的区域位于子域时。

在您的.env 文件中:

SESSION_DOMAIN=".yourdomain.tld"

app/Providers/RouteServiceProvider.php 中,在boot() 方法中将api 更改为web

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

routes/api.php:

Route::middleware('auth')->get('/user', function (Request $request) 
    return $request->user();
);

在你的resources/js/bootstrap.js:

window.axios.defaults.withCredentials = true;

修改bootstrap.js文件后,需要再次运行npm run dev重新编译。


现在,您应该可以在前端 javascript 中使用 Axios。无论是 jQuery 还是 Vue,无论你在使用什么。

axios.get('/api/user')
    .then(response => console.dir(response.data))
    .catch(error => console.log(error));

【讨论】:

我更惊讶于我 3 年前的问题仍然受到关注哈哈,但很高兴知道!有用的信息【参考方案2】:

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

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

在默认的RouteServiceProvider中,将mapApiRoutes函数改为使用web中间件:

protected function mapApiRoutes()

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


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

routes/api.php 文件中:

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

如果您想确保它是一个 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);
    

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

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

【讨论】:

即使改变它,如果我把我的 api.php Route::middleware('auth:api')->get('/latest', 'InternalApiController@latest'); 我仍然得到同样的错误 @K3nzie 您仍在使用 auth:api 来检查 api 身份验证保护。只需使用middleware('auth') 即可。 ok 修复了它,但是,这样 API 端点可以从 Web 访问,而只希望它在 Vue 中使用,这可能吗? @K3nzie 我添加了一个简单的 AJAX 检查中间件,这将有助于隐藏 API 端点以防止浏览器意外导航。 像魅力一样工作!你救了我【参考方案3】:

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

【讨论】:

以上是关于使用 axios 的 API 请求总是未经 Laravel API 授权的主要内容,如果未能解决你的问题,请参考以下文章

在 Laravel 护照、vueJS 和 Axios 中获得未经授权的 401

对 MailChimp API v3 的发布请求总是返回未经授权的

在Laravel护照,vueJS和Axios中未经授权获得401

React Native axios 总是返回“请求失败,状态码 400”

Laravel 5.3 + Passport:总是未经身份验证的错误

使用 React 时,rails api-only 应用程序中出现 401 未经授权的错误