如何使用 Laravel Sanctum 和 React 修复 401 Unauthorized 错误?

Posted

技术标签:

【中文标题】如何使用 Laravel Sanctum 和 React 修复 401 Unauthorized 错误?【英文标题】:How do I fix the 401 Unauthorized error with Laravel Sanctum and React? 【发布时间】:2021-05-28 18:31:54 【问题描述】:

我有以下设置:

与 Homestead 一起运行的 Laravel 域 laravel-api.test 指向我的 Homestead 环境 React (npx create-react-app) 使用自定义主机在本地运行 app.laravel-api.test:3000

Laravel

在我的路线(routes/api.php)我添加了两条路线:

Route::post('login', [App\Http\Controllers\LoginController::class, 'login']);
Route::middleware('auth:sanctum')->get('books', [App\Http\Controllers\BookController::class, 'list']);

在我的config/cors.php 中我添加了:

'paths' => ['api/*', 'sanctum/csrf-cookie'],

'allowed_methods' => ['*'],

'allowed_origins' => ['*'],

'allowed_origins_patterns' => [],

'allowed_headers' => ['*'],

'exposed_headers' => [],

'max_age' => 0,

'supports_credentials' => true,

在我的.env 中,我添加了以下内容:

SESSION_DOMAIN=.laravel-api.test
SANCTUM_STATEFUL_DOMAINS=app.laravel-api.test:3000

反应

在 React 中我做了一个函数来轻松发送 Axios 请求:

import axios from "axios";

const apiClient = axios.create(
  baseURL: "http://laravel-api.test",
  withCredentials: true,
);

export default apiClient;

然后我为我的登录表单做了一个提交功能:

const handleSubmit: FormEventHandler = (e) => 
    e.preventDefault();

    apiClient.get("sanctum/csrf-cookie").then((response) => 
      apiClient
        .post("api/login", 
          email: email,
          password: password,
        )
        .then((response) => 
          console.log(response);
        )
        .catch((error) => 
          console.error(error);
        );
    );
  ;
现在我对sanctum/csrf-cookie 的请求进展顺利,我将收到 Cookie。 login 的请求也很顺利,它将返回用户。

问题

但现在的问题是我做了一个按钮来请求书籍列表(/api/books)。请求正在发送,但我收到 401 Unauthorized 错误和 "message":"Unauthenticated." 响应。

我已经阅读了很多论坛,但我找不到我的情况并且没有答案。我可以尝试什么?如何调试圣所并找出我未通过身份验证的原因。

是饼干吗?是主机名吗?

import React from "react";
import apiClient from "../services/api";

interface Book 
  id: string;
  title: string;


const Books = () => 
  const [books, setBooks] = React.useState<Book[]>([]);
  
  React.useEffect(() => 
    apiClient
      .get("/api/books")
      .then((response) => 
        setBooks(response.data);
      )
      .catch((error) => console.error(error));
  , []);

  const bookList = books.map((book) => <li key=book.id>book.title</li>);

  return <ul>bookList</ul>;
;

export default Books;

【问题讨论】:

这是我几个月来一直试图解决的一个问题。这个问题让我暂时放弃了这个项目,因为无缘无故的 401 错误我无法继续前进。最近我回到了这个项目,发现我自己正在寻找解决方案。我还不得不就我的观察提出一个问题github.com/laravel/framework/discussions/36419。到目前为止还没有解决方案,但是当我得到一个时我会放弃,如果找到也不要忘记放弃 urs。 【参考方案1】:

我认为首先你需要设置不同的主机,你的反应应用应该有主域 laravel-api.test 没有端口,你的后端应该是:api。 laravel-api.test

在你的 .env 中你应该有这个:

SESSION_DOMAIN=.laravel-api.test
SANCTUM_STATEFUL_DOMAINS=laravel-api.test

也在您的后端:/config/cors.php 中,将 support_credentials 更改为 true :

'supports_credentials' => true,

【讨论】:

【参考方案2】:

最后,我每次更改 .env 文件时都必须清除配置缓存。

【讨论】:

以上是关于如何使用 Laravel Sanctum 和 React 修复 401 Unauthorized 错误?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Laravel Sanctum 处理 SPA 和基于令牌的身份验证

如何在没有典型 laravel /login 的情况下使用 laravel sanctum

如何选择使用 Laravel Sanctum 进行身份验证?

为啥我的 CSRF 令牌与 Laravel 和 Sanctum 不匹配?

使用 laravel sanctum 在 vue 中保存令牌的最佳方法

Laravel Sanctum 无法使用 Postman 登录