1

我正在构建一个多租户应用程序,其想法是管理员通过主域(http://myapp.app)访问仪表板,普通用户访问其各自子域(http://tenant上的另一个仪表板-a.myapp.app)。

为了实现这一点,我创建了一个使用会话驱动程序admins 提供程序的自定义警卫(管理员),这是一个使用eloquent 驱动程序和我的表admins的自定义提供程序。

// config/auth.php

'guards' => [
    'web' => [
        'driver' => 'session',
        'provider' => 'users',
    ],

   'api' => [
        'driver' => 'jwt',
        'provider' => 'users',
   ],

   'admin' => [
        'driver' => 'session',
        'provider' => 'admins',
   ]
],


'providers' => [
   'users' => [
       'driver' => 'eloquent',
       'model' => Monica\Models\User::class,
    ],

   'admins' => [
       'driver' => 'eloquent',
       'model' => Monica\Models\Admin::class,
   ],
],

在阅读了大量关于身份验证如何工作的文档后,我得到了管理员仪表板工作事件以及重置密码系统,但子域的一部分仍然存在一些问题。

租户子域上的普通用户的登录似乎正在工作,因为我让我的用户登录了,如果我检查了记住选项,这将反映在数据库获取令牌上。

最重要的问题是当我尝试使用身份验证功能(外观或注入)检索用户时,我无法获取用户,该方法总是返回 null。

我试图为 auth 对象指定保护,但仍然无法正常工作。

当我使用保护对象时,它有一个成员用户,它假设包含已登录的用户,但它始终为空,如果您要问我为什么需要该用户,那是因为我需要检查用户的权限。

我的理论是我的会话仅适用于主域而不适用于子域,或者我需要指定另一个 cookie 但老实说我只是在猜测。

我什至不知道我的代码的哪一部分对发布有用,但如果你与这个问题有关,欢迎你给我的每一盏灯,如果你需要更多信息或我的特定代码,请告诉我.

提前致谢

更新

这是摘录UserController.php

use Illuminate\Auth\AuthManager as Auth;
use Illuminate\Contracts\Auth\Access\Gate;
use Monica\Http\Controllers\Controller;

class UsersController extends Controller
{
    protected $auth;

    protected $gate;

    public function __construct(Auth $auth, Gate $gate)
    {
        $this->middleware('web');
        $this->auth = $auth;
        $this->gate = $gate;
        $this->auth->guard('web');
        $this->auth->shouldUse('web');
        $u = $this->auth->guard();
        dd($u);
    }
}

这是转储的保护对象:

SessionGuard {#311 ▼
  #name: "admin"
  #lastAttempted: null
  #viaRemember: false
  #session: Store {#294 ▼
    #id: "XIWy7hEJRuX1cL2bBN7pf7DqT54PpbTyYBXPv6He"
    #name: "no_named_app_session"
    #attributes: array:5 [▼
       "_token" => "RrTXOZwj56Nk9OqxkdkLdDztfZb6TeW2knVf5xc7"
       "_previous" => array:1 [▼
       "url" => "http://monica.app/admin/admins"
    ]
      "_flash" => array:2 [▼
        "old" => []
        "new" => []
    ]
      "url" => []
      "login_admin_59ba36addc2b2f9401580f014c7f58ea4e30989d" => "66f4aab0-6566-11e8-b51d-673dcbafed23"
]
  #handler: FileSessionHandler {#295 ▼
    #files: Filesystem {#115}
    #path: "/home/vagrant/Code/PHP/monica/storage/framework/sessions"
    #minutes: "120"
  }
  #started: true
}
  #cookie: CookieJar {#292 ▼
    #path: "/"
    #domain: null
    #secure: false
    #sameSite: null
    #queued: []
  }
  #request: Request {#42 ▶}
  #events: Dispatcher {#26 ▶}
  #loggedOut: false
  #recallAttempted: false
  #user: Admin {#328 ▶}
  #provider: EloquentUserProvider {#308 ▼
    #hasher: BcryptHasher {#310 ▶}
    #model: "Monica\Models\Admin"
  }
 }
4

2 回答 2

2

在查看 Laravel 请求的生命周期后,我发现在执行控制器类的构造函数时,用户在AuthGuard对象中不可用如果您尝试在控制器构造函数上访问已登录的用户

public function __construct(Auth $auth, Gate $gate)
{
    $this->auth = $auth;
    $this->gate = $gate;
    $this->middleware('auth:web');
    $this->auth->shouldUse('web');
    $user = $this->auth->user()  // null
}

但是如果你在控制器方法中访问用户,用户将被返回

public function index($subdomain)
{
    $user = $this->auth->user()->toArray();
}

这是用户 var 转储

array:6 [▼
    "id" => "670732c0-6566-11e8-93c6-41f6face77c8"
    "tenant_id" => "66f815e0-6566-11e8-83b2-37a662a96205"
    "name" => "user"
    "email" => "user@aetech.com"
    "created_at" => "2018-06-01 06:38:32"
    "updated_at" => "2018-06-01 06:38:32"
]
于 2018-06-27T03:37:21.670 回答
1

您可以尝试几种不同的方法来动态设置防护。

1.使用auth()->shouldUse('the_guard')

在中间件或控制器的构造函数中,shouldUse根据域或主机名将守卫的名称传递给方法:

if (request()->getHttpHost() === 'myapp.com') {
    auth()->shouldUse('admin');
} else {
    auth()->shouldUse('api'); // use the guard for tenants
}

2. 再次在中间件或控制器构造函数中覆盖默认配置config/auth.php

if (request()->getHttpHost() === 'myapp.com') {
    config(['auth.defaults.guard' => 'admin');
} else {
    config(['auth.defaults.guard' => 'api'); // use the guard for tenants
}

如果您使用自定义逻辑登录,请确保Authenticable使用以下方法之一设置模型auth:登录、一次、尝试等。

我使用第一种方法,shouldUse跨项目使用抽象基控制器类,所有其他适用的控制器都从该类继承。希望这可以帮助。

于 2018-06-23T05:10:17.990 回答