Laravel 5.6 - 如何使用同一文件夹 SPA 的会话来验证 API?
Laravel 5.6 - How to authenticate API using sessions for same folder SPA?
我在同一个 Laravel 项目中有一个 React SPA。 login/signup/logout 和所有其他 js 视图都在 js 文件夹中,并使用 axios api 调用所有 POST/GET
请求。我想为嵌入式 SPA 使用默认的基于 Laravel session 的 Web 身份验证,因为它位于同一个项目文件夹中,并且它将是 only javascript 客户端访问它。这个 api 不需要对 public 开放,只是为了这个 react 应用程序,它是一个 SPA,用于速度和良好的用户体验,而不是整页重新加载。
我以前尝试过使用 Passport,一个多月后,我仍然无法让它按预期工作。我不想处理令牌、访问令牌、刷新令牌、撤销令牌、CSRF 等。只是开箱即用的简单的基于 Laravel session 的身份验证,可以在网络上轻松运行,但想要它适用于我的 React 应用程序。唯一的 blade 文件是 index.blade.php
,其中包含反应 app.js
知道我们如何才能做到这一点吗?
更新 1:
实施@ceejayoz 的建议后:
You have to add the various Session/Cookie middlewares in
app/Http/Kernel.php (stuff like
\Illuminate\Session\Middleware\StartSession::class) to the API routes.
我添加到$middlewareGroups.api
以匹配app/Http/Kernel.php
中的web
中间件:
'api' => [
'throttle:60,1',
'bindings',
// Newly added middleware to match web middleware
\App\Http\Middleware\EncryptCookies::class
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
我意识到发生了两个问题:
- 在session中table,即使没有登录,在加载应用程序主页(或任何页面)时,多个session被插入[=21] =] table。用户登录后,不应该在这个table 只中插入一个新的singlesession吗?
用户登录后,在浏览器中手动刷新页面并调用受保护的路由时,我得到一个 401 Unauthenticated
,它指向我在 Illuminate/Auth/GuardHelpers.php
:
public function authenticate() {
if (! is_null($user = $this->user())) {
return $user;
}
throw new AuthenticationException; // throws this 401 exception on logged in page refresh when fetching data from private route
}
一些补充说明:
- 在
config/auth.php
中,我将 guards.api.driver
更新为 session
而不是 token
。
- 在
routes/api.php
中,我将受保护的路由包裹在 auth 中间件中,如下所示:Route::group(['middleware' => 'auth'], function() { PRIVATE ROUTES HERE }
- 在
config/session.php
我有 'domain' => '.mydomain.com'
我将这些 headers 与每个 axios api 请求一起发回,如下所示:
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
let token = document.head.querySelector('meta[name="csrf-token"]');
window.axios.defaults.headers.common['X-CSRF-TOKEN'] = token.content;
知道我们如何解决这 2 个问题吗?
这是可行的(我自己也为一些应用做了同样的事情)。
默认情况下,routes/api.php
中的路由没有可用的会话,但您可以在 app/Http/Kernel.php
中添加各种 Session/Cookie 中间件(例如 \Illuminate\Session\Middleware\StartSession::class
)前往 API 条路线。
正如@ljubadr 所建议的那样,您也可以将 API 路由直接放在 routes/web.php
中,尽管这可能意味着您需要进行其他更改(例如删除 CSRF 保护来自网络路由)。
看起来你的会话没有持续。
检查您是否更改了 config/session.php
中可能产生问题的任何值。
您可以检查默认的会话配置值 here
根据评论,@Wonka 通过更改
解决了他的问题
'same_site' => 'strict'
到
'same_site' => null
我在同一个 Laravel 项目中有一个 React SPA。 login/signup/logout 和所有其他 js 视图都在 js 文件夹中,并使用 axios api 调用所有 POST/GET
请求。我想为嵌入式 SPA 使用默认的基于 Laravel session 的 Web 身份验证,因为它位于同一个项目文件夹中,并且它将是 only javascript 客户端访问它。这个 api 不需要对 public 开放,只是为了这个 react 应用程序,它是一个 SPA,用于速度和良好的用户体验,而不是整页重新加载。
我以前尝试过使用 Passport,一个多月后,我仍然无法让它按预期工作。我不想处理令牌、访问令牌、刷新令牌、撤销令牌、CSRF 等。只是开箱即用的简单的基于 Laravel session 的身份验证,可以在网络上轻松运行,但想要它适用于我的 React 应用程序。唯一的 blade 文件是 index.blade.php
,其中包含反应 app.js
知道我们如何才能做到这一点吗?
更新 1:
实施@ceejayoz 的建议后:
You have to add the various Session/Cookie middlewares in app/Http/Kernel.php (stuff like \Illuminate\Session\Middleware\StartSession::class) to the API routes.
我添加到$middlewareGroups.api
以匹配app/Http/Kernel.php
中的web
中间件:
'api' => [
'throttle:60,1',
'bindings',
// Newly added middleware to match web middleware
\App\Http\Middleware\EncryptCookies::class
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
我意识到发生了两个问题:
- 在session中table,即使没有登录,在加载应用程序主页(或任何页面)时,多个session被插入[=21] =] table。用户登录后,不应该在这个table 只中插入一个新的singlesession吗?
用户登录后,在浏览器中手动刷新页面并调用受保护的路由时,我得到一个
401 Unauthenticated
,它指向我在Illuminate/Auth/GuardHelpers.php
:public function authenticate() { if (! is_null($user = $this->user())) { return $user; } throw new AuthenticationException; // throws this 401 exception on logged in page refresh when fetching data from private route }
一些补充说明:
- 在
config/auth.php
中,我将guards.api.driver
更新为session
而不是token
。 - 在
routes/api.php
中,我将受保护的路由包裹在 auth 中间件中,如下所示:Route::group(['middleware' => 'auth'], function() { PRIVATE ROUTES HERE }
- 在
config/session.php
我有'domain' => '.mydomain.com'
我将这些 headers 与每个 axios api 请求一起发回,如下所示:
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest'; let token = document.head.querySelector('meta[name="csrf-token"]'); window.axios.defaults.headers.common['X-CSRF-TOKEN'] = token.content;
知道我们如何解决这 2 个问题吗?
这是可行的(我自己也为一些应用做了同样的事情)。
默认情况下,routes/api.php
中的路由没有可用的会话,但您可以在 app/Http/Kernel.php
中添加各种 Session/Cookie 中间件(例如 \Illuminate\Session\Middleware\StartSession::class
)前往 API 条路线。
正如@ljubadr 所建议的那样,您也可以将 API 路由直接放在 routes/web.php
中,尽管这可能意味着您需要进行其他更改(例如删除 CSRF 保护来自网络路由)。
看起来你的会话没有持续。
检查您是否更改了 config/session.php
中可能产生问题的任何值。
您可以检查默认的会话配置值 here
根据评论,@Wonka 通过更改
解决了他的问题'same_site' => 'strict'
到
'same_site' => null