资讯专栏INFORMATION COLUMN

途牛原创|大话权限中心的PHP架构之道

miracledan / 2698人阅读

摘要:权限中心的依赖声明声明依赖关系检查代码规范声明开发依赖命名空间检查代码规范,执行单元测试。单元测试持续交付一切都如此的完美,没有测试,又如何可以证明这件事情的完美,又如何可以保障交付的质量。

权限管理是无线运营系统中的核心模块,通过访问控制策略的配置,来约定人与资源的访问关系。

本文着重讲解如何通过PHP来构建一个灵活、通用、安全的权限管理系统。

关于权限

首先我们来聊聊权限。

权限系统一直以来是我们应用系统不可缺少的一个部分,若每个应用系统都重新对系统的权限进行设计,以满足不同系统用户的需求,将会浪费我们不少宝贵时间,所以花时间来设计一个相对通用的权限系统是很有意义的。

系统目标:对应用系统的所有对象资源和数据资源进行权限控制,比如 应用系统的功能菜单、各个界面的按钮、数据显示的列以及各种行级数据 进行权限的操控。

权限模型

设计初期,我们学习了Amazon的 IAM ,经过对比分析,最终我们选用 RBAC3模型 来指导系统的设计工作。

RBAC认为权限授权实际上是Who、What、How的问题。在RBAC模型中,who、what、how构成了访问权限三元组,也就是“Who对What(Which)进行How的操作”。

Who:权限的拥用者或主体(如Principal、User、Group、Role、Actor等等)

What:权限针对的对象或资源(Resource、Class)。

How:具体的权限(Privilege,正向授权与负向授权)。

Operator:操作。表明对What的How操作。也就是Privilege+Resource

Role:角色,一定数量的权限的集合。权限分配的单位与载体,目的是隔离User与Privilege的逻辑关系.

PHP架构之道

「如何用PHP构建我们的权限中心」

接下来我们将从 编码规范、依赖管理、数据源架构、数据处理、单元测试 等方面来体验一把PHP的神奇之旅。

编码规范

好的编码规范可以改善软件的可读性,可以促进团队成长,可以减少Bug,可以降低维护成本,可以。。。(这么X,我们必须要推广)

PHP社区一直百花齐放,拥有大量的函数库、框架和组件,因而PHP代码遵循或尽量接近同一个代码风格就非常重要。

框架互操作组(即PHP标准组)发布了一系列推荐风格。

阅读PSR-0

阅读PSR-1

阅读PSR-2 Coding Style Guide

阅读PSR-4 Autoloader

权限中心的目录结构:

-- /tuniu/rbac
|-- src
|   |-- App //应用建模层
|   |   |-- City.php
|   |   |-- Cms.php
|   |   |-- Menu.php
|   |-- App.php
|   |-- Auth.php
|   |-- Orm //ActiveRecord层
|   |   |-- App
|   |   |   |-- Resource
|   |   |   |   |-- Map.php
|   |   |   |-- Resource.php
|   |   |   |-- User.php
|   |   |-- App.php
|   |   |-- Log.php
|   |   |-- Role
|   |   |   |-- User.php
|   |   |-- Role.php
|   |   |-- Rule.php
|   |   |-- User.php
|   |-- Orm.php
|   |-- Utils.php
|-- tests //测试
|   |-- bootstrap.php
|   |-- fixtures
|   |   |-- null.yml
|   |   |-- rbac
|   |   |   |-- app.yml
|   |   |   |-- auth.yml
|   |   |   |-- role.yml
|   |-- rbac
|   |   |-- appTest.php
|   |   |-- authTest.php
|   |   |-- roleTest.php
|-- vendor
|-- composer.json
|-- composer.lock
|-- phpunit.xml
|-- README.md

PSR-2,权限应用资源类:

namespace TuniuRbacOrmApp;

use TuniuRbacOrm;
use TuniuRbacOrmApp;
use TuniuRbacOrmAppResourceMap;
use TuniuRbacOrmRule;
use TuniuRbacOrmUser;

class Resource extends Orm {}

PSR-4,命名空间的约定:

()*

类名 文件路径
TuniuRbacOrmAppResource /tuniu/rbac/src/Orm/App/Resource.php
TuniuRbacAppCms /tuniu/rbac/src/App/Cms.php
依赖管理

Composer 是PHP中用来管理依赖(dependency)关系的工具。你可以在自己的项目中声明所依赖的外部工具库(libraries),Composer会帮你安装这些依赖的库文件。

权限中心的依赖声明:

{
    "name": "tuniu/rbac",
    "require": { //声明依赖关系
        "php": ">=5.3.0",
        "squizlabs/php_codesniffer": "2.*", //PHP_CodeSniffer检查代码规范
        "php-activerecord/php-activerecord": "dev-master" //ActiveRecord
    },
    "require-dev": { //声明开发依赖
        "phpunit/phpunit": "~4.6",
        "phpunit/dbunit": ">=1.2"
    },
    "autoload": {
        "psr-4": {
            "TuniuRbac": "src/" //命名空间
        }
    }
}

检查代码规范,执行单元测试。

$./vendor/bin/phpcs --config-set default_standard PSR2
$./vendor/bin/phpcs src
$./vendor/bin/phunit

^^^^^^ 眼涩,眼酸,眼疲劳,怎么办。。。

骚年,如果舒服了,就使劲往下滑动吧。。。

争渡,争渡,惊起一滩鸥鹭。

数据源架构

基于权限中心各表的关系(各种关联,各种回调),采用传统的模式,必将把精力耗在无尽的循环中。

于是乎,开始寻觅一种数据源的架构模式,Active Record很靠谱的出现了。

Active Record(中文名:活动记录)是一种领域模型模式,特点是一个模型类对应关系型数据库中的一个表,而模型类的一个实例对应表中的一行记录。

PHP ActiveRecord 是一个基于ActiveRecord设计模式开发的开源PHP/ORM库。它旨在大大简化与数据库的交互和减少手写SQL语句。它不同于其他的ORM,你不需要使用任何的代码生成器,也不费劲去手写、维护模型层的表映射文件。这个库的灵感来自Ruby on Rails,因此它也借鉴Ruby on Rails的想法和实现。(谁用谁知道)

下面介绍下这个小伙伴给编程带来的快乐:

Validation(数据验证)

validates_presence_of

validates_inclusion_of

场景(角色表数据约定)

/**
 * 1:约定角色类型的范围
 * 2:约定角色状态的范围
 */
public static $validates_inclusion_of = array(
    array("f_type", "in" => array("role", "group", "department", "member")),
    array("f_status", "in" => array(1,2))
);

/**
 * 设定角色名称、角色状态、角色类型、角色描述不能为空
 */
public static $validates_presence_of = array(
    array("f_name"),
    array("f_status"),
    array("f_type"),
    array("f_desc")
);

//录入数据不满足约定条件,就无法保存,再也不用担心那些脏脏的数据。

Callback(回调)

before_save

before_create

before_update

before_destroy

after_save

after_create

after_update

after_destroy

场景1(角色表操作记录)

//定义回调函数
public static $before_save = array("setMisc");

//每当角色表保存之前,都默默的把数据格式好,好开心。。。
public function setMisc()
{
    //创建时间,创建人
    $this->is_new_record() && ($this->f_create_at = date("Y-m-d H:i:s"));
    $this->is_new_record() && ($this->f_create_by = $this->op);
    //更新时间,更新人
    $this->f_update_by = $this->op; //操作人
    $this->f_update_at = date("Y-m-d H:i:s"); //操作时间
}

场景2(新增资源,推送资源映射表):

//定义回调函数
public static $after_save = array("syncRelations");

//每当资源保存之后,自动把资源数据中的映射字段值,推送给资源映射表。
public function syncRelations()
{
    //获取资源的映射字段
    $mapFiledValue = $this->getMapFiledValue();

    $mapFiledValue
        ? $this->addMap($mapFiledValue)
        : Map::removeAllByResourceId($this->id);
}

场景3(角色删除):

//定义回调函数
public static $after_destroy = array("deleteRelations");

//每当角色删除时,自动把系统中角色的成员和角色的资源规则清空,而且是事务的。
public function deleteRelations()
{
    UserRelations::removeAllByRoleId($this->id);
    RuleRelatinos::removeAllByRoleId($this->id);
}

Association(关联)

has_many

场景(新增角色用户)

//定义角色表和角色用户表的关系
public static $has_many = array(
    array(
        "relations",
        "foreign_key" => "f_role_id",
        "class_name" => "TuniuRbacOrmRoleUser",
    )
);

//新增角色用户,默默的把role_id传递给了角色用户表,此处如果用SQL,简直不忍直视。
Role::first()->create_relation(
    array(
        "f_user_id" => $uid
    )
);

事务(一致性与安全性)

权限系统中数据一致性和数据安全性的重要性是不言而喻,不用事务会被BS的。

在此我们郑重承诺,权限系统中每一次数据增删改请求,都是事务处理的。

比如角色保存:

self::transaction(
    function () use ($params, &$role) {

        $role->f_name   = $params["name"];
        $role->f_status = $params["status"];
        $role->f_type   = $params["type"];
        $role->f_desc   = $params["desc"];

        if ($role->is_invalid()) {
            throw new Exception("角色相关操作失败", "900202");
        }

        $role->save();
    }
);

篇幅有限,这个小伙伴的战斗力场景远甚于此。

坦白的说,用AR是一种编程享受。

单元测试(持续交付)

一切都如此的完美,没有测试,又如何可以证明这件事情的完美,又如何可以保障交付的质量。

PHPUnit 是一个轻量级的PHP测试框架。它是在PHP5下面对JUnit3系列版本的完整移植,是xUnit测试框架家族的一员(它们都基于模式先锋Kent Beck的设计)。

单元测试是一种提高软件质量非常有效的方法,但很重要的是我们要去实践和体会。

简单的介绍下权限管理中的角色行为测试用例:

角色行为测试

数据集(YAML)

t_rbac_user:
    -
        f_id: 1
        f_name: "zhaoyang2"
        f_create_at: "2013-10-10 17:04:05"
t_rbac_role_user:
    -
        f_id: 1
        f_user_id: 1
        f_role_id: 1
t_rbac_role:
    -
        f_id: 1
        f_name: "运营研发部-1"
        f_status: 1,
        f_type: "department"
        f_desc: "我们是运营研发部-1"
        f_create_at: "2013-10-10 17:04:05"
        f_create_by: "zhaoyang2"
        f_update_by: "zhaoyang2"

测试代码:

//预设数据集
public function getDataSet()
{
    return new PHPUnit_Extensions_Database_DataSet_YamlDataSet(
        fixture("rbac/role.yml")
    );
}

/**
 * 权限操作-异常验证
 * @expectedException Exception
 * @expectedExceptionMessage 您无权运营当前数据
 */
public function testRoleDeleteException()
{
    Role::first()->remove();
}

/**
 * 权限操作-删除验证
 */
public function testRoleDelete()
{
    Role::first()->remove("zhaoyang2");

    //验证数据行
    $this->assertEquals(1, $this->getConnection()->getRowCount(Role::$table_name));
    $this->assertEquals(1, $this->getConnection()->getRowCount(UserRelation::$table_name));
}

鉴权用例和应用管理用例,远比这个复杂,感兴趣的同学可以去 Fork 一把,了解下PHPUNIT的魅力。

PHPUNIT很强大,想合理运用的话,没有任何捷径,开始写测试用例吧。。

结束语

其实说架构算上下,就是和大家分享下权限中心的PHP之道。

高效便捷的使用PHP服务我们的工作。

多交流,多分享,书写更好的PHP代码,享受编程和技术所带来的快乐。

RBAC

PHP之道

深入理解PHP内核

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/21552.html

相关文章

  • 途牛原创途牛无线权限系统架构设计与实践

    摘要:认为权限授权实际上是的问题。具体的权限,正向授权与负向授权。应用建模业务场景权限管理鉴权设计应用建模系统架构上支撑权限系统灵活配置,不僵硬字段,不僵硬行为,基于各种业务权限管控的特征灵活设计。表示许可权与角色之间多对多的指派关系。 序 之前写过一篇大话权限中心的PHP架构之道,主要是从软件工程角度介绍,如何通过编码规范、依赖管理、数据源架构、事务处理、单元测试等技术,来保障权限系统的高...

    TwIStOy 评论0 收藏0
  • 途牛原创途牛无线权限系统架构设计与实践

    摘要:认为权限授权实际上是的问题。具体的权限,正向授权与负向授权。应用建模业务场景权限管理鉴权设计应用建模系统架构上支撑权限系统灵活配置,不僵硬字段,不僵硬行为,基于各种业务权限管控的特征灵活设计。表示许可权与角色之间多对多的指派关系。 序 之前写过一篇大话权限中心的PHP架构之道,主要是从软件工程角度介绍,如何通过编码规范、依赖管理、数据源架构、事务处理、单元测试等技术,来保障权限系统的高...

    姘搁『 评论0 收藏0
  • 途牛原创|无线中心运营研发Redis酷实践

    摘要:从年月开始,的开发由作者目前就职赞助。武器一览无线运营播种机模型动态表单属性中心标签系统权限中心模型位置管理一切皆位置回到主题,下面就为大家详细介绍下,我们如何玩耍。场景包括页面缓存限速器页面性能分析状态统计智能提醒异常线路。 Redis-简介 Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。从2...

    zoomdong 评论0 收藏0
  • 途牛原创途牛周刊

    摘要:的本质是团队博客,关注互联网创业技术,每周推荐篇优质文章。坚持争取做到每周更新,与读者一起进步。第十一期第十期第九期第八期第七期第六期第五期第四期第三期切换至,第二期发布。创刊,用发布了第一次。 Tuniu Weekly Inspired By 《湾区日报》 我们团队也想基于这种模式,让大家感受到技术的人文。 《Tuniu Weekly》就这样产生了。 《Tuniu Weekly》...

    ThreeWords 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<