如何混合isAuthorized和Auth的功能->;在CakePHP中允许/拒绝一个方法?

如何混合isAuthorized和Auth的功能->;在CakePHP中允许/拒绝一个方法?,cakephp,authentication,Cakephp,Authentication,在我的设计中,一个操作有一个等级,访问它需要0-10(0是来宾[未登录],10是管理员)。每个用户都有一个等级,0-10。如果你有等级或更高,你可以访问该动作,否则你不能。很好很简单,这就是我所需要的 问题是CakePHP希望我用两个不同的概念来处理动作。我必须将它们标记为Auth->allow/deny,以确定Auth系统是否会干扰它们,然后我使用isAuthorized()控制对它们的访问 我的授权非常适合我的需要。。。除了我想要访问级别为0的任何操作都必须是Auth->allow()。。。

在我的设计中,一个操作有一个等级,访问它需要0-10(0是来宾[未登录],10是管理员)。每个用户都有一个等级,0-10。如果你有等级或更高,你可以访问该动作,否则你不能。很好很简单,这就是我所需要的

问题是CakePHP希望我用两个不同的概念来处理动作。我必须将它们标记为Auth->allow/deny,以确定Auth系统是否会干扰它们,然后我使用isAuthorized()控制对它们的访问

我的授权非常适合我的需要。。。除了我想要访问级别为0的任何操作都必须是Auth->allow()。。。然后完全忽略我的未授权方法。如果我拒绝所有页面,则在检查是否已授权之前,登录会在排名为0的页面上触发,因此即使我通过该页面授予授权,该用户也必须首先登录

有没有办法将这两个系统合并在一起,或者有一个简单的方法来取代它?大部分的认证系统是伟大的,并照顾我的业务,而我不必弄乱它。。。但这很尴尬,当我没有注意到混合的允许/拒绝或其他东西时,会引起问题


谢谢

在我看来,唯一的方法就是创建一个来宾用户。这是因为Auth组件在访问
isAuthorized()
之前检查用户是否存在,如您所述

您可以通过直接写入会话来实现这一点。这将告诉Auth组件有人登录,因此将调用
isAuthorized()
方法

AppController

public function beforeFilter() {
  // if no one is logged in, log in a guest
  if (!$this->Auth->user()) {
    $this->Session->write(AuthComponent::$sessionKey, array(
      'User' => array(
        'id' => 0
       )
    ));
  }
}

public function isAuthorized($user) {
  $authorized = false;
  if ($this->Auth->user('id') == 0) {
    // public guest user access
  }
  // other logic
  return $authorized;
}
public $components = array(
  'Auth' => array(
    'authenticate' => array(
      'Form',
      'Guest' // tell Cake to try Form authentication then Guest authentication
    )
  )
);

public function beforeFilter() {
  if (!$this->Auth->user()) {
    // no user? log in a guest (this will fail form authentication
    // then try guest authentication)
    $this->Auth->login();
  }
}

public function isAuthorized($user) {
  $authorized = false;
  if ($this->Auth->user('id') == 0) {
    // public guest user access
  }
  // other logic
  return $authorized;
}
一种可能更好的方法是使用自定义身份验证对象,它基本上告诉Cake使用该类来帮助进行身份验证。这将逻辑拆分为一个单独的类,使其更易于测试甚至禁用

app/Controller/Component/Auth/GuestAuthenticate.php

App::uses('BaseAuthenticate', 'Controller/Component/Auth');

class GuestAuthenticate extends BaseAuthenticate {
    public function authenticate(CakeRequest $request, CakeResponse $response) {
        // no real authentication logic, just return a guest user
        return array('User' => array('id' => 0));
    }
}
AppController

public function beforeFilter() {
  // if no one is logged in, log in a guest
  if (!$this->Auth->user()) {
    $this->Session->write(AuthComponent::$sessionKey, array(
      'User' => array(
        'id' => 0
       )
    ));
  }
}

public function isAuthorized($user) {
  $authorized = false;
  if ($this->Auth->user('id') == 0) {
    // public guest user access
  }
  // other logic
  return $authorized;
}
public $components = array(
  'Auth' => array(
    'authenticate' => array(
      'Form',
      'Guest' // tell Cake to try Form authentication then Guest authentication
    )
  )
);

public function beforeFilter() {
  if (!$this->Auth->user()) {
    // no user? log in a guest (this will fail form authentication
    // then try guest authentication)
    $this->Auth->login();
  }
}

public function isAuthorized($user) {
  $authorized = false;
  if ($this->Auth->user('id') == 0) {
    // public guest user access
  }
  // other logic
  return $authorized;
}

您可以在此处找到有关自定义身份验证对象的更多信息:

在我看来,唯一的方法是创建来宾用户。这是因为Auth组件在访问
isAuthorized()
之前检查用户是否存在,如您所述

您可以通过直接写入会话来实现这一点。这将告诉Auth组件有人登录,因此将调用
isAuthorized()
方法

AppController

public function beforeFilter() {
  // if no one is logged in, log in a guest
  if (!$this->Auth->user()) {
    $this->Session->write(AuthComponent::$sessionKey, array(
      'User' => array(
        'id' => 0
       )
    ));
  }
}

public function isAuthorized($user) {
  $authorized = false;
  if ($this->Auth->user('id') == 0) {
    // public guest user access
  }
  // other logic
  return $authorized;
}
public $components = array(
  'Auth' => array(
    'authenticate' => array(
      'Form',
      'Guest' // tell Cake to try Form authentication then Guest authentication
    )
  )
);

public function beforeFilter() {
  if (!$this->Auth->user()) {
    // no user? log in a guest (this will fail form authentication
    // then try guest authentication)
    $this->Auth->login();
  }
}

public function isAuthorized($user) {
  $authorized = false;
  if ($this->Auth->user('id') == 0) {
    // public guest user access
  }
  // other logic
  return $authorized;
}
一种可能更好的方法是使用自定义身份验证对象,它基本上告诉Cake使用该类来帮助进行身份验证。这将逻辑拆分为一个单独的类,使其更易于测试甚至禁用

app/Controller/Component/Auth/GuestAuthenticate.php

App::uses('BaseAuthenticate', 'Controller/Component/Auth');

class GuestAuthenticate extends BaseAuthenticate {
    public function authenticate(CakeRequest $request, CakeResponse $response) {
        // no real authentication logic, just return a guest user
        return array('User' => array('id' => 0));
    }
}
AppController

public function beforeFilter() {
  // if no one is logged in, log in a guest
  if (!$this->Auth->user()) {
    $this->Session->write(AuthComponent::$sessionKey, array(
      'User' => array(
        'id' => 0
       )
    ));
  }
}

public function isAuthorized($user) {
  $authorized = false;
  if ($this->Auth->user('id') == 0) {
    // public guest user access
  }
  // other logic
  return $authorized;
}
public $components = array(
  'Auth' => array(
    'authenticate' => array(
      'Form',
      'Guest' // tell Cake to try Form authentication then Guest authentication
    )
  )
);

public function beforeFilter() {
  if (!$this->Auth->user()) {
    // no user? log in a guest (this will fail form authentication
    // then try guest authentication)
    $this->Auth->login();
  }
}

public function isAuthorized($user) {
  $authorized = false;
  if ($this->Auth->user('id') == 0) {
    // public guest user access
  }
  // other logic
  return $authorized;
}

您可以在此处找到有关自定义身份验证对象的更多信息:

也许这已经得到了令人满意的处理,但我有一个解决方案

在我的AppController中,我有以下内容:

正如您所发现的,如果您没有显式授权操作,即使允许公开,也会拒绝已验证的用户执行这些操作。这段代码只是使isAuthorized()方法遵守Auth->allow()列表中的设置


这似乎对我有用,所以我希望它能有所帮助。

也许这已经得到了令人满意的处理,但我有一个解决方案

在我的AppController中,我有以下内容:

正如您所发现的,如果您没有显式授权操作,即使允许公开,也会拒绝已验证的用户执行这些操作。这段代码只是使isAuthorized()方法遵守Auth->allow()列表中的设置


这似乎对我有用,所以我希望它能有所帮助。

这只是一个想法,但你可以拥有一个排名为0的来宾帐户,并在没有用户登录时将其设为当前用户。你如何将级别映射到一个操作?莱克特博士-这听起来是一个非常有希望的想法。所以你建议在客人第一次到达时强制登录到一个级别为0的客户帐户,然后如果他们的级别为0,则保留可供登录的选项?你能预见到我需要解决的任何问题吗?Burzum-我刚刚在isAuthorized方法中做了if($this->action==='xyz')或switch。然后我只调用我编写的一个方法来检查排名,该方法返回true/false。这只是一个想法,但您可以拥有排名为0的来宾帐户,并在没有用户登录时将其设置为当前用户。如何将级别映射到操作?莱克特博士-听起来这是一个非常有前途的想法。所以你建议在客人第一次到达时强制登录到一个级别为0的客户帐户,然后如果他们的级别为0,则保留可供登录的选项?你能预见到我需要解决的任何问题吗?Burzum-我刚刚在isAuthorized方法中做了if($this->action==='xyz')或switch。然后我只调用我编写的一个方法来检查返回true/false的秩。您所做的几乎正是我想要做的。但问题是:默认情况下,Auth系统拒绝一切。这意味着,您必须先登录,甚至会考虑ISIS授权的方法。如果我首先允许所有操作,那么所有操作都将完全公开,而未授权的操作将被忽略。基本上,拒绝一切都很好,除了访问网站的客人,因为他们必须先注册一个帐户,然后才能检查授权。客人可以访问什么?通常只有几页,对吗?在这种情况下,
Auth::allow()。例如,页面控制器上的Auth::allow('*')
,这本身就是问题所在。不只是几页,他们可以