如何处理每页权限?

时间:2012-01-09 15:44:10

标签: php mysql database-design

我有 X 页数,我希望在每页的页面上为用户设置权限。

最初我在考虑使用bitmask。但是我已经意识到,如果我的页数超过一定数量(只能在MySQL unsigned BIGINT列中存储64页),那么我的位掩码的十进制等值可能会变得太大。

e.g。第64页的十进制等值为18,446,744,073,709,551,615,这只是让它查看一页。

那么您将如何在每页,每个用户的基础上设置大量页面的查看权限?

4 个答案:

答案 0 :(得分:3)

为什么不将它们存储为数据库中的多对多关系?

user_id | page_id
      1 |       1
      1 |       2
      2 |       1
      2 |       3

然后,您可以使用SELECT * from users_pages WHERE user_id =?获取用户可以看到的网页,或者您可以通过SELECT * from users_pages WHERE page_id = ? and user_id = ?确定是否允许用户查看特定网页。

答案 1 :(得分:2)

我曾经看过一个系统,其中包含一个与UNIX文件权限类似的用户权限表 - 用户可以在此表中读取或写入(以及编辑内容,它是CMS)任何页面。 “页面”由唯一名称标识,以便每个页面都知道它自己的名称,当访问页面时,它还知道哪个用户正在访问它,然后查找该用户对该页面的权限,并在显示相应的编辑控件时可用。

示例:

users
  user_name    (other columns)
  ----------
  bob
  lisa
  ADMIN

pages
  page_id  page_name (other columns)
  ----------------------
  1        landing_page
  2        products
  3        corporate_about_us

page_permissions
  page_id user_name read write
  ------------------------------
  1       Bob       Y
  1       ADMIN     Y    Y
  2       ADMIN     Y    

这告诉我们,当ADMIN登录并加载ID = 1的页面时,他们将能够对页面进行更改。但是,Bob不会。

我看到的实际系统比这更复杂(我很确定它实际上使用rwx之类的权限而不是指标列,我更喜欢)而且我不记得细节所以我正在简化。

您可以根据需要修改和自定义此方案。


如果您担心数百(或数千)个页面 AND 存储数千个用户的权限记录而导致的大量数据,您已经运行了实际的性能测试,以证明它是一个主要问题是,您可以提出一个默认模式,例如:除非另有明确说明,否则用户始终在任何地方都只读。然后你可以这样做:

users
  user_name    read_only_user   (other columns)
  ---------------------------------------------
  bob          Y
  lisa         Y
  ADMIN

pages
  page_id  page_name (other columns)
  ----------------------
  1        landing_page
  2        products
  3        corporate_about_us

page_permissions
  page_id user_name read write
  ------------------------------
  1       ADMIN     Y    Y
  2       ADMIN     Y    

这样,您只需要为page_permission的用户存储read_only_user <> 'Y'条记录。缺点是你需要更多的逻辑来处理这种设置。

答案 2 :(得分:0)

我会保持简单,只有Pages UsersUserPagePermissions表。最后一个只是页面和用户之间的地图。

答案 3 :(得分:0)

<?php
/**
 * acl_parser.inc.php
 * this is not a formal system of acls but a simplification
 * there are a number of attribuates known which are given
 * a value of 1, unknown attributes are numbered 0
 * then logical combinations of attributes are evaluated
 *
 * example of rule is:
 *  personnel and manager not (plonker or temp)
 * note that rules are NOT case sensitive
 * @package simple_acl
 * @author Colin McKinnon <colin.mckinnon at google's public mail service>
 * @copyright 24th November 2007 
 */
/**
 * implements the parser
 *
 * IMORTANT: this method uses PHP's 'eval()' function - this has SERIOUS security implications unless you are 100%
 * sure of the provenance of data supplied to it.
 * The class has no built-in data access and  must be populated with facts and a rule before evaluation
 */
class acl_parser
{
    /**
     * @var array of fact=>value, private (use method to update)
     * e.g. $fact['timenow']=date('His'); $fact['manager']=true;
     */
   var $facts;
    /**
     * @var string the acl to check, private (use method to update)
     * e.g. $rule="personnel and manager not (plonker or temp) and (timenow > '0900' and timenow < '1730')";
    */
   var $rule;
   /**
    * @var string the expression which was eval'd - for debugging
    */
    var $rewrite;
   /**
    * constructor
    * @param $facts array can be set/updated later
    * @see var $facts
    * @return null
    */
   function acl_parser($facts=false)
   {
        // set up default subsitutions for operators....
       $this->facts=array('and' => '*', // must come between expressions
           'or' => '+', // must come between expressions
           'not' => '!', // must come before expression
           'true' => '1'
           );
        // did we get some data to set up?
       if (is_array($facts)) {
           foreach ($facts as $name=>$val) {
               $this->add_fact($name, $val);
           }
       }
       $this->rule===false;
   }
   /**
    * wrapper to control access to $this->rule
    * @param string
    * @return bool - true if successful
    *
    * could be used to set site specific policies relating to rules - e.g. no less than / greater than
    */
   function set_rule($rule)
   {
       $this->rule=$rule;
       return(true);
   }
    /**
    * set a single fact for addition
    */
    function add_fact($name, $value)
    {
       $this->facts[$name]=$value;
    }
   /**
    * evaluate the rule applying the known facts
    * @return bool
    */
   function test($rule=false)
   {
       if ($rule!=false) {
           $this->rule=$rule;
       }
       if (($this->rule===false) || (!count($this->facts))) {
           trigger_error("acl_parser not initialised with rule and facts");
           return(false);
       }
       $match=array();
       $replace=array();
       foreach ($this->facts as $name=>$val) {
           $match[]='/([^a-z]|^)(' . $name . ')([^a-z]|$)/i';
           $replace[]='${1}' . $val . '${3}';
       }
       // this macro gets added on end to pick up on undefined elements
       $match[]='/[a-z]+/i';
       $replace[]='0';
       $rewrite=preg_replace($match,$replace,$this->rule);
    $this->rewrite=$rewrite;
       return((bool)eval("return($rewrite);"));
   }
}

?>