php - cakePHP在模型中使用请求/身份验证数据的3个最佳实践(基于帐户的云服务)

原文 标签 php session cakephp cakephp-3.0

我正在创建一个云服务,其中有多个帐户,每个帐户有多个用户。用户只能登录其帐户。每个帐户都有一个唯一的别名。 (例如 abc )。如果用户转到其子域(例如 abc.cloud.service ),则他们可以登录其帐户并仅查看分配给该帐户的内容。登录效果很好。

我添加了htaccess重定向规则,该规则将子域转换为查询。

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{HTTP_HOST} ^([a-z0-9]+)\.cloud\.service$ [NC]
RewriteRule ^ index.php?alias=%1 [L]

因此,在所有控制器中,我都有别名作为可用查询。为了保证只允许用户查看其内容,所有模型都与一个帐户相关。每当我想对其中一个模型执行查找操作时,我都想确保结果属于正确的帐户。我正在beforeFind中做到这一点。
// beforeFind of models which are related to an account
public function beforeFind(Event $event, Query $query, ArrayObject $options, $primary) {
    if ($primary) {
        $query->contain(['Accounts']);
    }
}

为了获得正确的帐户,我在Accounts模型中有一个beforeFind,用于检查查询。
// beforeFind of the Accounts model
public function beforeFind (Event $event, Query $query, ArrayObject $options, $primary) {
    if (isset($_GET['alias'])) {
        $query->where(['Accounts.alias' => $_GET['alias']]);
    }
}

由于我所有的查找操作都只返回该帐户允许的数据,因此效果很好。但是我知道我在做什么可能不被称为最佳实践。 问题1:有更好的方法吗?我不知道如何访问模型中的查询数据?

问题2:
保存任何类型的内容时,我需要确保将其分配给正确的帐户。

选项1(由于发生过多而无效)
我可以在所有保存 call 之前手动分配Accound ID,具体取决于用户帐户ID。但是我将有太多的保存 call ,所以我想在这里有一个更好的解决方案。

选项2(这是我现在正在做的)
我将一些代码添加到beforeSave到与该帐户相关的所有模型中:
// beforeSave in models related to Accounts model
public function beforeSave(Event $event, Entity $entity, ArrayObject $options)
{
    if (!isset($_SESSION['Auth']['User']['account_id'])) {
        $entity->account_id = $_SESSION['Auth']['User']['account_id'];
    }
}

再次可以很好地工作,但是我也知道cakePHP不建议直接访问 session 变量。 问题2,这里有更好的解决方案吗?我在模型中找不到访问身份验证数据的有效解决方案

最佳答案

首先,我想说的是,在模型中访问授权信息不是最佳实践,因为它不能很好地将控制器逻辑和业务逻辑之间的关注点分离。

我会说,在这里使用的最佳情况是调度过滤器,也许是这样的:

class SubdomainFilter extends DispatcherFilter
{
    public function beforeFilter(Event $event)
    {
        if (isset($_GET['alias'])) {
            $event->data['request']->subdomain_alias = $_GET['alias'];
        }
    }
}

然后在bootstrap.php中初始化新的过滤器:
DispatchFactory::add('SubdomainFilter');

然后最后,您可以访问子域别名,将其作为附加到控制器中请求对象的属性,以作为参数传递给模型函数:
class FooController extends AppController
{
    public function exampleEndpoint() {
        $your_table->findFunction($this->request->subdomain_alias);
        $your_table->saveFunction($this->request->subdomain_alias, $data);
}

您可以在CakePHP 3 here中了解有关调度过滤器的更多信息。

相关文章:

mysql - 如何在CakePHP中从MySQL获取所有表名

php - 为什么只有最后一项保存在数据库中?

php - PHP:正则表达式替换,而忽略html标签之间的内容

php - 我可以在满足条件的复杂查询中排除行吗? (结合WHERE +多个AND)

javascript - 如何使用jQuery调用PHP函数从MYSQL获取更新数据

php - 警告:session_destroy()?

php - 显示数据库中的一行并移至下一列

asp.net - ASP.Net中的客户端会话超时重定向

java - JSP中的会话问题

javascript - 表格行的JavaScript比较,以红色突出显示一行(CakePHP)