【问题标题】:Store additional session data with custom auth driver使用自定义身份验证驱动程序存储其他会话数据
【发布时间】:2014-05-18 14:34:46
【问题描述】:

我为我的 Laravel 应用创建了一个自定义 Auth 驱动程序。现在我想知道向我的身份验证会话添加额外数据的标准方法是什么。

我创建了一个自定义守卫:

class MyAppGuard extends Guard {
    //...
}

用户提供者:

class MyAppUserProvider implements UserProviderInterface {
    //...
}

我已经在global.php注册了我的驱动程序:

Auth::extend('mydriver', function($app) {
    $provider = new \MyApp\Auth\MyAppUserProvider($app['hash'], 'User');
    return new \MyApp\Auth\MyAppGuard($provider, $app['session.store']);
});

一切似乎都正常,我可以调用MyAppGuard 的自定义方法和Auth::myCustomMethod() 等等。

我现在想将用户的所有权限添加到会话中,以便可以通过Auth::permissions() 访问它们,就像用户通过Auth::user() 一样。

我应该怎么做,我确信我可以用一些丑陋的方式来做,但必须有一个最佳实践?

【问题讨论】:

  • 你是如何检查 API 的?

标签: php laravel laravel-4


【解决方案1】:

在您的提供程序类中执行以下操作:

 public function permission()
 {
     // get the id of the authentication users session
     $id = $this->session->get($this->getName());

     // now do a query to get the users permission by his/her id
     $permission = ...

     return $permission;
 }

这样称呼

 Auth::permission();

如果你查看 Laravel Auth 的代码。每次调用 Auth::user(); 时它都会创建一个新的用户模型,除非它是相同的请求,那么它们只会立即返回现有数据。

他们在会话中存储的唯一内容是用户 ID。所以我不建议使用会话来存储您的权限。只需使用会话中现有的用户 ID 并查询权限,然后返回数据。

您可以从Guard.php 访问用户标识符,例如:

$id = $this->session->get($this->getName());

注意:我不是专家。

更新

添加类似:

protected $permission;

然后设置成这样

$this->permission = $permission;

这与 laravel 用于Auth::user() 的方法相同。我认为这不会减慢您的申请速度。

然后在您的permission() 函数中检查$this->permission 是否已设置。

if (!is_null($this->permission))
{
     return $this->permission;
}

// then do the rest here like getting the permission
...

这样,如果请求的权限已经存在,那么它会返回它,而不是再次执行整个查询(可能会使其变慢的部分)。

【讨论】:

  • 感谢您的回答。我已经尝试过一些非常相似的东西,但无法让它工作。真的很想为每个请求省略数据库查询。也因为查询非常复杂(3-4 个连接)。所以我要么将权限数据存储在会话中,要么存储在缓存中。我不确定什么更好,我猜会话更有意义。我明天再试一次。
  • Mhh 我认为我失败的部分是将实际数据存储在会话中。为每个请求再次检索数据并将其存储在对象中实际上工作得很好。也试过$this->session->put('permissions', $permissions);。但要到明天才能给你真正的反馈。
  • 哦,您看到我的预览回答并建议将其存储在会话中?呵呵。过了一会儿,出于安全预防措施,我改变主意不这样做,所以我编辑了我的答案。您会注意到我有很多编辑,因为我在尝试回答时也在学习。 :) 祝你好运。
  • 在尝试回答的同时学习是 SO 最好的事情 :)
  • 同意。希望得到一些关于哪种方法实际上更好的反馈:)
【解决方案2】:

现有的 Guard 类为您提供了所需的所有工具。

在模型上请求关系会缓存关系,登录用户的模型是存储在会话数据中的。

利用现有的 user() 函数,该函数检查当前登录的用户或记住我的 cookie,然后存储会话数据。

MyAppGuard 内部:

public function permissions() {
  if ($user = $this->user()) {
    return $user->permissions;
  } else {
    return $user;
  }
}

无需将权限预先加载到用户模型中。由于调用 permissions() 会将关系缓存到登录用户模型中,因此数据存储在会话中。

您可以通过覆盖 setUser() 函数来预先加载权限

public function setUser() {
  parent::setUser();
  $this->user->load('permissions');
}

这将在用户登录后立即将权限存储到会话数据中,而不是在第一次调用 permissions() 函数时缓存权限。但是,这真的没有区别。


作为侧边栏,这些在技术上都不是必需的。如果您要在代码中的任何位置调用 Auth::user()->permissions,您将在当前会话中缓存当前登录用户的凭据。所以 Auth::permissions() 函数有点毫无意义。

【讨论】:

  • 谢谢。唯一的问题是我不能只加载关系,因为我的权限系统有点复杂。我需要为不同的对象获得不同的权限。有一个函数可以生成权限数组。但也许我仍然可以以某种方式将其添加给用户以使用现有的记忆功能。
  • @MarcelGwerder 没错。这几乎就是我想要解释的(即使没有急切加载)。 User 模型是存储在会话中的。因此,跟踪 Permissions 数据的最简单方法是将其存储在 User 模型中。这才是处理这些事情的正确方式。
  • 从我看到user() 代码时可以看到,用户ID 是唯一存储在会话中的东西。每个请求通过$user = $this->provider->retrieveByID($id) 从数据库中提取一次实际用户模型,因此将权限附加到setUser 中的用户不会将它们存储在会话中。还是我忽略了什么……
猜你喜欢
  • 1970-01-01
  • 2017-11-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-22
  • 1970-01-01
  • 1970-01-01
  • 2017-03-14
相关资源
最近更新 更多