草庐IT

php - 了解用户权限以及如何应用它

coder 2024-01-05 原文

我正在使用 Social Engine 为站点开发模块,它使用 Zend 框架。我是 Zend Framework 和 Social Engine 的新手,但在 OOP 和 MVC 架构方面有经验,因此可以相对快速地掌握基础知识。

这是我正在开发的一个测试模块,所以刚刚构建了一个简单的模块,用户可以在其中创建、编辑或删除 CD 信息。然后有一个小部件,可以显示在他们喜欢的地方,显示 CD 信息。

我现在正处于需要设置人们可以看到哪些 CD 等权限的地步。所以我研究了其他模块,发现 Poll 模块是一个具体的例子。

查看其他模块后,我意识到当您创建某些内容时,它们会让用户手动设置权限。

因此将此代码添加到我的表单中以创建具有相关权限的选择框:

$auth = Engine_Api::_()->authorization()->context;
$user = Engine_Api::_()->user()->getViewer();
$viewOptions = (array) Engine_Api::_()->authorization()->getAdapter('levels')->getAllowed('ryan', $user, 'auth_view');
$viewOptions = array_intersect_key($availableLabels, array_flip($viewOptions));

$privacy = null;

if( !empty($viewOptions) && count($viewOptions) >= 1 ) {
    // Make a hidden field
    if(count($viewOptions) == 1) {
        //$this->addElement('hidden', 'auth_view', array('value' => key($viewOptions)));
        $privacy  = new Zend_Form_Element_Hidden('auth_view');
        $privacy->setValue(key($viewOptions));
        // Make select box
    } else {
        $privacy = new Zend_Form_Element_Select('auth_view');
        $privacy->setLabel('Privacy')
                ->setDescription('Who may see this CD?')
                ->setMultiOptions($viewOptions)
                ->setValue(key($viewOptions));
        /*$this->addElement('Select', 'auth_view', array(
            'label' => 'Privacy',
            'description' => 'Who may see this CD?',
            'multiOptions' => $viewOptions,
            'value' => key($viewOptions),
        ));*/
    }
}

$this->addElements(array($artist, $title, $privacy, $submit));

老实说,除了显然创建一个选择框并用指定的值填充它之外,我不完全确定这段代码的作用。

因此,如果用户选择“每个人”,每个人都应该能够删除和编辑该 CD,等等。

显然我认为 Controller 必须有一些代码来处理确定用户是否有权查看每张 cd 等。

所以扫描 Poll Controller 我发现这是在 Controller 的 init 函数中:

public function init() {
    // Get subject
    $poll = null;
    if( null !== ($pollIdentity = $this->_getParam('poll_id')) ) {
        $poll = Engine_Api::_()->getItem('poll', $pollIdentity);
        if( null !== $poll ) {
            Engine_Api::_()->core()->setSubject($poll);
        }
    }

    // Get viewer
    $this->view->viewer = $viewer = Engine_Api::_()->user()->getViewer();
    $this->view->viewer_id = Engine_Api::_()->user()->getViewer()->getIdentity();

    // only show polls if authorized
    $resource = ( $poll ? $poll : 'poll' );
    $viewer = ( $viewer && $viewer->getIdentity() ? $viewer : null );
    if( !$this->_helper->requireAuth()->setAuthParams($resource, $viewer, 'view')->isValid() ) {
        return;
    }
}

在顶部的每个操作中,它们都有一些不同的授权代码,一个这样的例子是 editAction,它在顶部有这个代码:

// Check auth
if( !$this->_helper->requireUser()->isValid() ) {
    return;
}
if( !$this->_helper->requireSubject()->isValid() ) {
    return;
}
if( !$this->_helper->requireAuth()->setAuthParams(null, null, 'edit')->isValid() ) {
    return;
}

在同一个 Action 中还有其他几个我不明白他们在做什么,下面是来自轮询 Controller 中 editAction 的随机片段:

$auth = Engine_Api::_()->authorization()->context;
$roles = array('owner', 'owner_member', 'owner_member_member', 'owner_network', 'registered', 'everyone');

// Populate form with current settings
$form->search->setValue($poll->search);
foreach( $roles as $role ) {
    if( 1 === $auth->isAllowed($poll, $role, 'view') ) {
        $form->auth_view->setValue($role);
    }
    if( 1 === $auth->isAllowed($poll, $role, 'comment') ) {
        $form->auth_comment->setValue($role);
    }
}

// CREATE AUTH STUFF HERE
if( empty($values['auth_view']) ) {
    $values['auth_view'] = array('everyone');
}
if( empty($values['auth_comment']) ) {
    $values['auth_comment'] = array('everyone');
}

$viewMax = array_search($values['auth_view'], $roles);
$commentMax = array_search($values['auth_comment'], $roles);

我的问题是,如果我 100% 诚实,我真的不太了解以上任何一项,在坐了几天并用谷歌搜索我的手指受伤后,我仍然不知道我是否真的有任何线索。是否可以为我解决以上任何问题,帮助向我解释事情,如果可能的话,我如何将我想要的权限应用到我的模块。

最佳答案

我将提供有关如何使用授权的简要说明,但需要通过查看 SocialEngine 的代码来推断更详细的信息。请注意,虽然我们不为 SocialEngine 编译文档,但我们的开发人员在我们的代码中使用了 PHPDocumentor 风格的语法,您可以使用像 Neatbeans (http://netbeans.org/) 这样的 IDE 来快速访问该信息。

SocialEngine 有一些 Controller Action 助手类,用于 Action Controller 中的查询授权:

  • application/modules/Authorization/Controller/Action/Helper/RequireAuth.php
  • application/modules/Core/Controller/Action/Helper/RequireAbstract.php
  • application/modules/Core/Controller/Action/Helper/RequireAdmin.php
  • application/modules/Core/Controller/Action/Helper/RequireSubject.php
  • application/modules/Core/Controller/Action/Helper/RequireUser.php

在大多数情况下,您唯一关心的是这些:

  • application/modules/Authorization/Controller/Action/Helper/RequireAuth.php
  • application/modules/Core/Controller/Action/Helper/RequireSubject.php
  • application/modules/Core/Controller/Action/Helper/RequireUser.php

可以在 Album_AlbumController 类中找到如何使用这些助手的一个很好的例子: 应用程序/模块/Album/controllers/AlbumController.php

public function init()
{
if( !$this->_helper->requireAuth()->setAuthParams('album', null, 'view')->isValid() ) return;

if( 0 !== ($photo_id = (int) $this->_getParam('photo_id')) &&
null !== ($photo = Engine_Api::_()->getItem('album_photo', $photo_id)) )
{
Engine_Api::_()->core()->setSubject($photo);
}

else if( 0 !== ($album_id = (int) $this->_getParam('album_id')) &&
null !== ($album = Engine_Api::_()->getItem('album', $album_id)) )
{
Engine_Api::_()->core()->setSubject($album);
}
}

public function editAction()
{
if( !$this->_helper->requireUser()->isValid() ) return;
if( !$this->_helper->requireSubject('album')->isValid() ) return;
if( !$this->_helper->requireAuth()->setAuthParams(null, null, 'edit')->isValid() ) return;

init 函数中的代码简单地设置了访问页面的要求,然后在 editAction 函数中,检查授权数据。 requireSubject 和 requireUser 助手非常简单:

  1. requireSubject 期望页面的主题设置在 上面的例子在 init 函数中完成
  2. requireUser 检查查看者是否是登录用户

requireAuth 帮助程序不太直接。为了简洁起见,我将省略大部分抽象的内部工作。最后,helper 指向 Authorization_Api_Core::isAllowed 函数: 应用程序/模块/授权/核心/Api.php

/**
* Gets the specified permission for the context
*
* @param Core_Model_Item_Abstract|string $resource The resource type or object that is being accessed
* @param Core_Model_Item_Abstract $role The item (user) performing the action
* @param string $action The name of the action being performed
* @return mixed 0/1 for allowed, or data for settings
*/
public function isAllowed($resource, $role, $action = 'view')

函数期望的 $resource 和 $role 对象是 Zend_Db_Table_Row 的实例,它在 SocialEngine 中被称为 Models 并且期望位于模块的 Models 目录中。调用 isAllowed 函数时,授权 API 将根据 engine4_authorization_allow、engine4_authorization_levels 和 engine4_authorization_permissions 表查询数据库。

  1. engine4_authorization_levels 表包含成员级别 由开箱即用的 SocialEngine 创建,以及自定义成员 从管理中的“管理”>“成员(member)级别”部分创建的级别 面板。
  2. engine4_authorization_permissions 表包含所有 default和admin指定的权限处理,比如member 电平设置。
  3. engine4_authorization_allow 包含 单个对象的权限数据。例如资料 关于谁能够查看相册的信息将放在那里。 engine4_authorization_allow.role_id 是否(映射到项目 模型的 ID)被允许访问 engine4_authorization_allow.resource_id(映射到项目 ID 型号)由 engine4_authorization_allow.value 列确定 其中应包含数字 0-5。

应用程序/模块/授权/Api/Core.php

class Authorization_Api_Core extends Core_Api_Abstract
{
/**
* Constants
*/
const LEVEL_DISALLOW = 0;
const LEVEL_ALLOW = 1;
const LEVEL_MODERATE = 2;
const LEVEL_NONBOOLEAN = 3;
const LEVEL_IGNORE = 4;
const LEVEL_SERIALIZED = 5;

0) 不允许访问链接的资源。这与允许表中不存在的行相同

1) 也允许访问链接的资源

2) 允许访问和管理资源(即 super 管理员、管理员和版主成员级别)

3-5) 因不允许而被忽略。这些需要一些自定义逻辑才能适本地处理授权。

关于php - 了解用户权限以及如何应用它,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11520448/

有关php - 了解用户权限以及如何应用它的更多相关文章

  1. ruby - 如何使用 Nokogiri 的 xpath 和 at_xpath 方法 - 2

    我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div

  2. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

    总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

  3. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  4. ruby-on-rails - 如何验证 update_all 是否实际在 Rails 中更新 - 2

    给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru

  5. ruby-on-rails - 'compass watch' 是如何工作的/它是如何与 rails 一起使用的 - 2

    我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t

  6. ruby - 将差异补丁应用于字符串/文件 - 2

    对于具有离线功能的智能手机应用程序,我正在为Xml文件创建单向文本同步。我希望我的服务器将增量/差异(例如GNU差异补丁)发送到目标设备。这是计划:Time=0Server:hasversion_1ofXmlfile(~800kiB)Client:hasversion_1ofXmlfile(~800kiB)Time=1Server:hasversion_1andversion_2ofXmlfile(each~800kiB)computesdeltaoftheseversions(=patch)(~10kiB)sendspatchtoClient(~10kiBtransferred)Cl

  7. ruby - 如何将脚本文件的末尾读取为数据文件(Perl 或任何其他语言) - 2

    我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚

  8. ruby - 什么是填充的 Base64 编码字符串以及如何在 ruby​​ 中生成它们? - 2

    我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%

  9. ruby - 如何指定 Rack 处理程序 - 2

    Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack

  10. ruby - 如何每月在 Heroku 运行一次 Scheduler 插件? - 2

    在选择我想要运行操作的频率时,唯一的选项是“每天”、“每小时”和“每10分钟”。谢谢!我想为我的Rails3.1应用程序运行调度程序。 最佳答案 这不是一个优雅的解决方案,但您可以安排它每天运行,并在实际开始工作之前检查日期是否为当月的第一天。 关于ruby-如何每月在Heroku运行一次Scheduler插件?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/8692687/

随机推荐