13

我将 Laravel Sanctum 与 Vuejs SPA 一起使用。两者都驻留在同一个顶级域

Laravel backend : app.demo.localhost
Vue SPA : app-spa.demo.localhost

当使用 axios 从 VueJS SPA 调用并且成功设置 XSRF-TOKEN 时,登录和注销(端点)工作正常,但是当我调用其他 api 端点时,它给了我 401 未授权。

在 axios 中,这是被设置的

axios.defaults.withCredentials = true;

我有以下配置

在 Laravel .env 中

SESSION_DRIVER=cookie
SESSION_DOMAIN=.demo.localhost
SANCTUM_STATEFUL_DOMAINS=app-spa.demo.localhost

在 Routes/Api.php 中

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

在 cors.php 中

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

'allowed_methods' => ['*'],

'allowed_origins' => ['*'],

'allowed_origins_patterns' => [],

'allowed_headers' => ['*'],

'exposed_headers' => [],

'max_age' => 0,

'supports_credentials' => true,

有人可以帮帮我吗?

4

7 回答 7

28

如果您使用的是 php artisan serve,请将端口号添加到 SANCTUM_STATEFUL_DOMAINS。因此,如果您的端口号是 8000:

SESSION_DRIVER=cookie
SESSION_DOMAIN=.demo.localhost
SANCTUM_STATEFUL_DOMAINS=app-spa.demo.localhost:8000

您的 SANCTUM_STATEFUL_DOMAINS 必须与浏览器中的 url 匹配。端口号不应在 SESSION_DOMAIN 上。

于 2020-07-01T17:18:42.130 回答
3

对于任何与 localhost 打交道的人:

SESSION_DRIVER=cookie    
SESSION_DOMAIN=localhost    
SANCTUM_STATEFUL_DOMAINS=localhost:8080(port number you use)
于 2021-01-14T11:39:47.193 回答
1

以下是我在设置 Laravel sanctum 时遵循的 8 个步骤,检查你是否遗漏了什么

步骤1 composer require laravel/sanctum

第2步 php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider

第三步 php artisan migrate(如果你使用水疗,你可以忽略这个)

Step4 从 app/http/kernel.php 取消注释这一行\Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,

Step5在 config/cors.php 更新'supports_credentials' => true,

Step6在 .env 文件中更新SESSION_DRIVER=cookie并添加新行SESSION_DOMAIN=localhost(即使您使用像 8080 这样的任何端口,只需在 session_domain 中提及localhost )

Step7 在 config/sanctum.php 中添加您的客户端域以及端口(如果是本地),如下所示,在我的情况下,对于 vue CLI 它通常是localhost:8080& 对于 nuxt its localhost:3000,代码如下

    'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf(
        '%s%s',
        'localhost,localhost:8000,localhost:8080,localhost:3000,127.0.0.1,127.0.0.1:8000,::1',
        env('APP_URL') ? ','.parse_url(env('APP_URL'), PHP_URL_HOST) : ''
    ))),

大多数情况下,如果您的有状态(第 7 步)设置不正确,您将获得 401 未授权,或者它会尝试将您重定向到主页以及 cors 策略错误

Step8在promise解决await之前不要忘记sanctum/csrf-cookie

    async login() {
      await axios.get("http://localhost:8000/sanctum/csrf-cookie");

      await axios.post("http://localhost:8000/login", {
        email: "kunal@gmail.com",
        password: "password",
      });

      let response = await axios.get("http://localhost:8000/api/user");
      console.log(response.data);
    },

于 2021-11-05T19:04:53.267 回答
1

我刚刚遇到了同样的问题。我按照官方文档配置了所有的选项,但是无法获得授权。

然后我用routes/web.php代替routes/api.php,这样可以很好的使用sanctum中间件。

现在问题似乎很明显了,Axios withCredentials 可能需要以正确的方式放置。

const http = axios.create({
    baseURL: API_URL,
    withCredentials: true
})

也许行不通。所以我添加{withCredentials: true}喜欢

http.get('/api/whoami', {withCredentials: true})
  .then(res => {
                console.log(res.data)
            })

然后它工作。

但是很奇怪的是现在正常了,不管我清除浏览器缓存、cookies还是Laravel的各种缓存,都没有以前的情况

于 2020-06-10T01:34:15.350 回答
0

我的问题是....(注意阅读)

如果您的 SPA 需要使用私有/在线广播频道进行身份验证,您应该将Broadcast::routes 方法调用放在您的 routes/api.php 文件中

于 2021-01-14T22:36:47.413 回答
0

嗨,我找到了解决方案。

我的 SPA 是在 3000 端口上工作的 Vue v3。我的后端也在 80 端口上工作。(laravel 8.1)

像这样在 config/sanctum.php 中创建有状态域

 'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf(
    '%s%s',
    'localhost:3000',
    env('APP_URL') ? ','.parse_url(env('APP_URL'), PHP_URL_HOST) : ''
))),

在他们的网站上只添加一个正确的域,神奇地为我工作。我在那之前写过所有可能的端口变体,这让我抓狂并且花费了几天几夜。

于 2022-02-05T23:49:02.220 回答
0

我的问题是我在错误的地方设置了域。我认为是一个域数组, in config/sanctum.php,但不是,需要放在字符串中:

好的:

    'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf(
        '%s%s',
'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,::1,myownlocaldomain.test,myownlocaldomain.test:8080', <-------- OK
        env('APP_URL') ? ','.parse_url(env('APP_URL'), PHP_URL_HOST) : ''
    ))),

坏的:

    'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf(
        '%s%s',
        'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,::1',
        env('APP_URL') ? ','.parse_url(env('APP_URL'), PHP_URL_HOST) : '',
        'myownlocaldomain.test', <----- BAD
        'myownlocaldomain.test:8080', <---- BAD
    ))),

我希望我能把几天的工作留给别人......

于 2022-02-22T14:32:21.707 回答