我正在尝试使 Fortify with sanctum 与名为 SPA 的自定义 Guard 一起工作。
管理员正在使用 Web Guard 登录后端。
用户正在登录将托管 VUEJS SPA 的子域。
管理员登录 -> https://test.local:8890/admin/login并重定向到https://test.local:8890/admin/dashboard有效 -> 好的
用户登录https://spa.test.local:8890 (vue app)。-> 好的作品
Vue文件:
import axios from 'axios'
axios.defaults.withCredentials = true;
axios.defaults.baseURL = 'https://test.local:8890'
export default {
name: 'Home',
components: {
HelloWorld
},
data: () => {
return {
email : 'doe@example.com',
password : 'Password1!'
}
},
methods : {
login() {
axios.get('/sanctum/csrf-cookie').then(response => {
console.log(response.code);
axios.post('web-api/login', {
email : this.email,
password : this.password
}).then(response => {
console.log(response);
}
).catch(error => {
console.log(error);
})
});
}}}
所以想法是用户不能在仪表板上登录并有一个单独的表
当我登录我的管理员时,我会转到仪表板。我在 chrome 中打开一个新选项卡,并以 vue 应用程序中子域上的用户身份登录。当我回到仪表板时,我仍然登录得很好,并且我以用户身份登录到另一个选项卡(超级)
但是在检查 chrome https://test.local:8890/和https://spa.test.local:8890/中的 cookie 时,共享相同的 cookie laravel_session 和 xcsrf 令牌......它们是相同的......
所以现在当我转到管理员选项卡并转到 web-api 路由https://test.local:8890/web-api/user我看到用户的凭据:
{"id":4,"first_name":"Happy","last_name":"Doe","email":"doe@example.com"}
但是我仍然可以以管理员身份访问我的仪表板。
config/auth.php
'defaults' => [
'guard' => 'web',
'passwords' => 'admins',
],
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'admins', //admin provider for web
],
'spa' => [
'driver' => 'session',
'provider' => 'users' //user provicer for spa (and api)
],
/*'api' => [
'driver' => 'token',
'provider' => 'users',
'hash' => false, //user provider
],*/
],
我已在 sanctum 配置中添加了保护参数。
配置/圣所:
'guard' => 'spa', //set sanctum guard to spa.
在内核文件中,我将所有内容从“web”中间件复制到“spa”,因为它的工作原理几乎相同。
内核.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,
],
'spa' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
'throttle:api',
\Illuminate\Routing\Middleware\SubstituteBindings::class
],
'api' => [
'throttle:api',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
];
在 env 文件中配置 Sanctum 参数。
.env :
SESSION_DOMAIN=test.local
SANCTUM_STATEFUL_DOMAINS=.test.local
将 SPA 添加到 routeServiceProvider 启动方法
RouteServiceProvider.php:
public function boot()
{
$this->configureRateLimiting();
$this->routes(function () {
Route::prefix('web-api')
->middleware('spa')
->namespace($this->namespace)
->group(base_path('routes/spa.php'));
/*Route::prefix('api')
->middleware('api')
->namespace($this->namespace)
->group(base_path('routes/api.php'));*/
Route::middleware('web')
->namespace($this->namespace)
->group(base_path('routes/web.php'));
});
}
然后我在 SpaAuthController 中的登录功能:(由 spa 使用)
public function loginSpa(Request $request){
//Regenerate session
$request->session()->regenerate();
$request->validate([
'email' => 'required|email',
'password' => 'required',
]);
$authAttempt = Auth::guard('spa')->attempt(['email' => $request->email, 'password' => $request->password]);
if($authAttempt){
$user = Auth::guard('spa')->user();
if (!$user->hasVerifiedEmail()){
abort(401, 'Email address not verified.');
}
if ($user->blocked){
abort(401, 'Your Account blocked.');
}
return response([],204);
}
return response(['message' => 'The provided credentials are incorrect.'],422);
}
默认情况下,强化控制器会处理整个 Web 登录...
发布 | 管理员/登录 | | Laravel\Fortify\Http\Controllers\AuthenticatedSessionController@store | 网络
在这一点上它变得有点有趣,我在这里做错了什么,我应该担心潜在的安全问题假设是的:D)