如何处理每页权限?
Posted
技术标签:
【中文标题】如何处理每页权限?【英文标题】:How to deal with per-page permissions? 【发布时间】:2012-01-09 15:44:10 【问题描述】:我有 X 个页面,我希望按页面为用户设置权限。
最初我想使用bitmask。但是我已经意识到,如果我的页数超过一定数量(在 mysql unsigned BIGINT
列中只能存储 64 页),那么我的位掩码的十进制等值可能会变得太大。
例如第 64 页的十进制等效值为 18,446,744,073,709,551,615
,这只是让它查看一页。
那么,您将如何针对每个页面、每个用户设置大量页面的查看权限?
【问题讨论】:
【参考方案1】:为什么不将它们作为多对多关系存储在您的数据库中?
喜欢
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 = ?
确定是否允许用户查看特定页面。
【讨论】:
当它扩展时这不是效率低下吗? 我不确定,但只要你为这两列设置了正确的索引,我猜它的性能会很好。【参考方案2】:我曾经看到一个系统有一个类似于 UNIX 文件权限的用户权限表——用户可以读取或写入(嗯,编辑内容,它是一个 CMS)该表中的任何页面。 “页面”由一个唯一的名称标识,以便每个页面都知道它自己的名称,并且当页面被访问时,它还知道哪个用户正在访问它,然后查找该用户对该页面的权限,并在何时显示适当的编辑控件可用。
例子:
用户 用户名(其他列) ---------- 鲍勃 丽莎 行政 页面 page_id page_name(其他列) ---------------------- 1个登陆页面 2 个产品 3 公司简介 page_permissions page_id 用户名 读写 ------------------------------ 1 鲍勃·Y 1 管理员 Y Y 2 管理员这告诉我们,当ADMIN
登录并加载 ID=1 的页面时,他们将能够对页面进行更改。但是,Bob
不会。
我看到的实际系统比这要复杂一些(我很确定它实际上使用rwx
之类的东西来获取权限,而不是我更喜欢的指标列),我不记得细节了,所以我m 化简。
您可以根据需要修改和自定义此方案。
如果您担心为成千上万的用户存储数百(或数千)页的权限记录会导致大量数据并且您已经运行了实际的性能测试以表明这是一个主要问题,您可以提出一个默认模式,例如:除非另有明确说明,否则用户始终在任何地方都是只读的。然后你可以这样做:
用户 user_name read_only_user(其他列) --------------------------------------------- 鲍勃·Y 丽莎 Y 行政 页面 page_id page_name(其他列) ---------------------- 1个登陆页面 2 个产品 3 公司简介 page_permissions page_id 用户名 读写 ------------------------------ 1 管理员 Y Y 2 管理员这样,您只需为read_only_user <> 'Y'
所在的用户存储page_permission
记录。缺点是您需要更多的逻辑来处理这种设置。
【讨论】:
【参考方案3】:我会保持简单,只使用 Pages
Users
和 UserPagePermissions
表。最后一个只是页面和用户之间的映射。
【讨论】:
@George 看到 vidnia 的回答。这就是我的建议。【参考方案4】:<?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);"));
?>
【讨论】:
我确信这很棒......但它有什么作用? 它使用一组事实评估任意表达式 - 参见示例以上是关于如何处理每页权限?的主要内容,如果未能解决你的问题,请参考以下文章
如何处理 Activity 和 Fragment 之外的权限请求?
如何处理 Android 运行时权限中的“不再询问”复选框?