我不太了解Laravel文档中的含义,所以我想确定一下。
我们的默认身份是一侧为Laravel,另一侧为Sanctum。
据说Sanctum可以执行令牌或仅实现身份验证。 :
对于此功能,Sanctum不使用任何类型的令牌。相反,Sanctum使用Laravel的内置基于cookie的会话身份验证服务。这提供了CSRF保护,会话身份验证以及防止通过XSS泄漏身份验证凭据的好处。只有当传入请求来自您自己的SPA前端(Vue.js)时,Sanctum才会尝试使用Cookie进行身份验证。
因此,如果从不使用令牌,那么Sanctum与默认的身份验证方法基本相同,对吗?基本上,它是否实现默认身份验证并在需要时添加令牌?如果是这样的话,圣所和护照有什么区别,因为他们做同样的事,但圣所据说是轻便的。这到底是什么意思?
感谢阅读
答案 0 :(得分:8)
因此,如果从不使用令牌,那么Sanctum与默认的身份验证方法基本相同,对吗?
是的,它在后台使用laravel的默认身份验证。
看看圣所护卫队(以下代码来自github。它最后一次提交于4月11日,圣所2.x)
<?php
namespace Laravel\Sanctum;
use Illuminate\Contracts\Auth\Factory as AuthFactory;
use Illuminate\Http\Request;
class Guard
{
/**
* The authentication factory implementation.
*
* @var \Illuminate\Contracts\Auth\Factory
*/
protected $auth;
/**
* The number of minutes tokens should be allowed to remain valid.
*
* @var int
*/
protected $expiration;
/**
* Create a new guard instance.
*
* @param \Illuminate\Contracts\Auth\Factory $auth
* @param int $expiration
* @return void
*/
public function __construct(AuthFactory $auth, $expiration = null)
{
$this->auth = $auth;
$this->expiration = $expiration;
}
/**
* Retrieve the authenticated user for the incoming request.
*
* @param \Illuminate\Http\Request $request
* @return mixed
*/
public function __invoke(Request $request)
{
if ($user = $this->auth->guard(config('sanctum.guard', 'web'))->user()) {
return $this->supportsTokens($user)
? $user->withAccessToken(new TransientToken)
: $user;
}
if ($token = $request->bearerToken()) {
$model = Sanctum::$personalAccessTokenModel;
$accessToken = $model::findToken($token);
if (! $accessToken ||
($this->expiration &&
$accessToken->created_at->lte(now()->subMinutes($this->expiration)))) {
return;
}
return $this->supportsTokens($accessToken->tokenable) ? $accessToken->tokenable->withAccessToken(
tap($accessToken->forceFill(['last_used_at' => now()]))->save()
) : null;
}
}
/**
* Determine if the tokenable model supports API tokens.
*
* @param mixed $tokenable
* @return bool
*/
protected function supportsTokens($tokenable = null)
{
return $tokenable && in_array(HasApiTokens::class, class_uses_recursive(
get_class($tokenable)
));
}
}
如果您选中_invoke()
方法,则
if ($user = $this->auth->guard(config('sanctum.guard', 'web'))->user()) {
return $this->supportsTokens($user)
? $user->withAccessToken(new TransientToken)
: $user;
}
使用以下身份找到经过身份验证的用户
$user = $this->auth->guard(config('sanctum.guard', 'web'))->user()
在检查了Sanctum配置文件之后,当前没有sanctum.guard
配置(这可能是将来的版本),因此默认情况下,Sanctum会使用web
防护进行检查,因此基本上是相同的东西作为您的默认网络路由。
但是您误解了圣殿的使用。 Sanctum用于API身份验证,而不用于Web身份验证(尽管它也可以用于Web身份验证)。 Sanctum的非令牌身份验证使您的SPA能够使用与移动应用程序相同的API(使用令牌身份验证),而无需令牌,并提供csrf和基于会话的身份验证的好处。
为帮助您更好地理解,假设您已经建立了一个使用令牌的API(如果已经使用sanctum令牌的话,则会简化事情)进行身份验证。现在,您希望构建一个使用相同API的SPA(可以在laravel项目本身内部构建,或者在同一域或不同域中的单独项目中构建),但是由于这是您自己构建的,因此可信站点,因此您不希望它使用令牌,而是使用laravel基于会话的默认身份验证以及csrf保护,同时还使用相同的api路由。 SPA将通过ajax与服务器通信。您还希望确保仅允许您的SPA使用基于会话的身份验证,而不允许其他第三方站点使用它。
这就是Sanctum的来历。您只需要将Sanctum中间件添加到api
的{{1}}路由组中
app/Http/Kernel.php
然后配置圣所以允许您的SPA的域并配置cors(请检查docs以了解如何执行此操作)。然后只需将use Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful;
'api' => [
EnsureFrontendRequestsAreStateful::class,
'throttle:60,1',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
中间件添加到您的路由中,就可以完成服务器端设置。
现在,如果请求具有令牌或请求是有状态的(会话cookie),这些路由将对用户进行身份验证。
现在,您的SPA无需令牌即可与API通信。
要获得csrf保护,请先调用auth:sanctum
请求,这将在cookie中设置csrf令牌,而axios会自动将其附加到后续请求中
csrf-cookie
圣所和护照有什么区别,因为他们做同样的事,但圣所据说很轻巧。
嗯,就像它说的那样,圣所是轻量级的。这是因为Passport提供了完整的Oauth功能,而Sanctum仅专注于创建和管理令牌。为了以简单的方式解释Oauth,您必须在不同的站点上看到过axios.get('/sanctum/csrf-cookie').then(response => {
// Login...
})
,Sign in with Google
,Sign in with Facebook
,然后可以使用google / facebook / github将其签名到那些站点帐户。这是可能的,因为Google,Facebook和Github提供了Oauth功能(仅是一个简单的示例,不会涉及太多细节)。对于大多数网站,您实际上并不需要Passport,因为它提供了许多不需要的功能。对于简单的api身份验证,Sanctum绰绰有余
答案 1 :(得分:3)
注意::此答案适用于Laravel Sanctum +同域SPA
要添加到这些答案中,默认的Laravel身份验证使用web
保护,因此您必须将其用于身份验证路由(对于同域SPA应用程序)。
例如,您可以创建指向Laravel的RegistersUsers
特性和AuthenticatesUsers
特性的自己的路线:
web.php
Route::group(['middleware' => ['guest', 'throttle:10,5']], function () {
Route::post('register', 'Auth\RegisterController@register')->name('register');
Route::post('login', 'Auth\LoginController@login')->name('login');
Route::post('password/email', 'Auth\ForgotPasswordController@sendResetLinkEmail');
Route::post('password/reset', 'Auth\ResetPasswordController@reset');
Route::post('email/verify/{user}', 'Auth\VerificationController@verify')->name('verification.verify');
Route::post('email/resend', 'Auth\VerificationController@resend');
Route::post('oauth/{driver}', 'Auth\OAuthController@redirectToProvider')->name('oauth.redirect');
Route::get('oauth/{driver}/callback', 'Auth\OAuthController@handleProviderCallback')->name('oauth.callback');
});
Route::post('logout', 'Auth\LoginController@logout')->name('logout');
但是请确保它们位于web.php
文件中。例如,如果它们在api.php
文件中,我会看到一些关于session store not on request
的奇怪错误,而RequestGuard::logout()
不是一个函数。我相信这与auth特性中通过$this->guard()
的默认身份验证保护有关,也与api.php
的{{1}}前缀有关。
/api
前缀似乎相关,因为如果您使用作曲者程序包Ziggy实现/api
和route('login')
,它们实际上将解析为route('logout')
和/api/login
。
我怀疑这导致了圣所的问题。解决方法是确保路由在/api/logout
中。如果某个人的配置相似,或者例如,如果他们在web.php
中声明了Auth::routes()
,则可能会重现此错误。
仔细检查您的 Kernel.php (应该是这样):
api.php
如果您的protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
// \Illuminate\Session\Middleware\AuthenticateSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
'api' => [
EnsureFrontendRequestsAreStateful::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
'throttle:60,1',
],
];
中间件组中有StartSession
,则说明您的配置不正确或不必要的盘绕。
这是我的工作 ./ config / auth.php 文件供您比较:
api
然后,您可以将'defaults' => [
'guard' => 'web',
'passwords' => 'users',
],
...
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'token',
'provider' => 'users',
'hash' => false,
],
],
中间件用于登录/注册路由,非常重要的是,然后应在guest
中声明所有JSON服务端点,并使用api.php
中间件在那些路线上。
一旦您认为它可以正常工作,我将为您提供两个测试/调试步骤:
一个:
auth:sanctum
和<app_name>_session
XSRF-TOKEN
,确保为remember: true
提供第三个cookie remember_web_<hash>
,并确保CSRF cookie不是(以便您的JavaScript可以访问它) 两个,请在单元测试中确保在httpOnly
之后看到以下内容:
$this->postJson(route('login'), $credentials)
应该返回true Auth::check()
应该返回用户对象Auth::user()
应该注销用户,然后紧接着Auth::logout()
应该返回true 在您确认这两个步骤之前,不要太兴奋,在成功验证这些步骤之后,请不要兴奋。这意味着您正在使用Laravel的默认身份验证逻辑。
出于良好的考虑,下面是通过JavaScript附加CSRF令牌的示例:
$this->assertGuest('web');
答案 2 :(得分:1)
Sanctum有两个单独的身份验证系统,有一个基于cookie的会话身份验证,该会话身份验证用于单页应用程序,在该应用程序中您将发送api请求(ajax,fetch等),而不是服务器端呈现(该请求在每次页面加载),sanctum可以使用此cookie(默认身份验证)而无需重新加载页面。
第二种身份验证系统是基于令牌的,旨在用于移动应用程序。