权限篇

首先,我们需要知道,用户组权限和用户权限是一样的

给用户组分配权限,无非就是给用户组的 permissions 字段赋值

给用户分配权限,无非就是给 用户 permissions 字段赋值

用户的权限优先级高于 用户组,所以相同的权限,定义在 用户 permissions 里面,会覆盖用户组的权限

然后我们看下

权限是什么?

权限,就是定义 你可以干什么,不可以干什么

比如:

我们的一个学生管理系统,分下列角色

一:管理组

  1. 1.录入员 (只可以录入学生信息)
  2. 2.教师 (只可以查看学生的基本信息)
  3. 3.校长 (可以删除学生信息,查看学生相册,看私房照)

二:用户组

  1. 1.学生 (只可以查询自己的信息)

我们分析上面所有动作

1.录入学生信息
2.查看学生信息
3.删除学生信息
4.查看学生相册

可以清晰的看到,管理组特征是 都拥有 查看学生的信息 这个权限,用户组 只有 查看信息的权限

权限对应为

  1. // 录入员
  2. $admin_1 = array(
  3. 'create.xuesheng'=>1, // 允许 创建学生
  4. 'xuesheng.chakan'=>0, // 拒绝 查看学生
  5. 'xuesheng.zhaopian'=>0, // 拒绝 看学生私房照
  6. );
  7. // 教师
  8. $admin_2 = array(
  9. 'xuesheng.chakan'=>1, // 允许 查看学生
  10. 'create.xuesheng'=>0, // 拒绝 创建学生
  11. 'xuesheng.zhaopian'=>0, //拒绝 看学生私房照
  12. );
  13. // 校长
  14. $admin_3 = array(
  15. 'create.xuesheng'=>1, // 允许 创建学生
  16. 'xuesheng.chakan'=>1, // 允许 查看学生
  17. 'xuesheng.zhaopian'=>1, //允许 看学生私房照
  18. );
  19. // 学生
  20. $user = array(
  21. 'xuesheng.chakan'=>1, //允许 查看学生
  22. 'create.xuesheng'=>0, //拒绝 创建学生
  23. 'xuesheng.zhaopian'=>0, //拒绝 看学生私房照
  24. );

上面的 0 1 代表什么意思呢?

在用户组权限中

  1. 0 : 拒绝
  2. 1 : 允许

在 用户权限中

  1. -1 : 拒绝
  2. 1 : 允许
  3. 0 : 继承

所以,我们给不同的组不同的权限,然后 给用户分配 用户组,用户的权限就 继承了用户组的权限啦

用户权限

我们曾经说过,用户权限等级 高于 用户组权限

比如:

一个 名为:张三 的老师,他属于管理组,但是,他得罪了校长,校长 给他打入冷宫30 天,期间不可以查看学生信息

这个时候,他原先就属于管理组,总不能给他 t 出 管理组吧?

这个时候,用户权限就派上用场了

  1. try
  2. {
  3. // 权限信息
  4. $per = array(
  5. 'xuesheng.chakan'=>-1
  6. );
  7. // 查出张三的信息
  8. $user = Sentry::findUserById(1);
  9. // login 字段是必须的
  10. $user->email = 'yccphp@163.com';
  11. $user->permissions = $per;
  12. // 执行更新
  13. if ($user->save())
  14. {
  15. // 更新成功
  16. }
  17. else
  18. {
  19. // 更新失败
  20. }
  21. }
  22. catch (Cartalyst\Sentry\Users\UserExistsException $e)
  23. {
  24. echo 'login 字段是必须的';
  25. }
  26. catch (Cartalyst\Sentry\Users\UserNotFoundException $e)
  27. {
  28. echo '用户不存在';
  29. }

假如 在管理员组中 xuesheng.chakan = 1 ,我们就可以定义用户权限 xuesheng.chakan = -1 ,这个时候,用户的权限,就覆盖了管理员组的权限,他就不可以访问了

验证用户是否具有指定的权限

比如我们检测 张三 老师 是否具有查看学生的权限

  1. try
  2. {
  3. // 查出张三老师
  4. $user = Sentry::findUserByID(1);
  5. // 要检查多个权限需要使用一个数组来进行参数传递
  6. if ($user->hasAccess('xuesheng.chakan'))
  7. {
  8. // 有权限
  9. }
  10. else
  11. {
  12. // 没权限
  13. }
  14. }
  15. catch (Cartalyst\Sentry\UserNotFoundException $e)
  16. {
  17. echo '用户不存在';
  18. }

这个检查权限,会先把 用户的权限查出来,用户组的权限查出来,然后合并,检查

验证用户是否具有指定权限的一种

也就是说,我给出很多权限,你只要有 具有一个,你就通过了

  1. try
  2. {
  3. $user = Sentry::getUserProvider()->findById(1);
  4. // admin 或者 foo 随便具有其中一个,你就通过
  5. if ($user->hasAnyAccess(array('admin', 'foo')))
  6. {
  7. // 有权限
  8. }
  9. else
  10. {
  11. // 没权限
  12. }
  13. }
  14. catch (Cartalyst\Sentry\UserNotFoundException $e)
  15. {
  16. echo '用户不存在';
  17. }

检查用户是否被激活

我们做网站的什么,通常用户没被激活是不可以登陆的,我们这就是检查他是不是被激活了

  1. try
  2. {
  3. $user = Sentry::findUserByLogin('yccphp@163.com');
  4. // 检查是否被激活
  5. if ($user->isActivated())
  6. {
  7. // 是
  8. }
  9. else
  10. {
  11. //否
  12. }
  13. }
  14. catch (Cartalyst\Sentry\Users\UserNotFoundException $e)
  15. {
  16. echo '用户不存在';
  17. }

检查用户是否存在一个指定的分组中

我们做权限控制的时候,有时候,一些东西,只能 admin 这个管理员组可以访问,所以我们也没必要做那么细,直接检查是否存在于 admin 这个管理员组就行了

  1. try
  2. {
  3. $user = Sentry::findUserByID(1);
  4. // 查询组
  5. $admin = Sentry::findGroupByName('admin');
  6. // 检查
  7. if ($user->inGroup($admin))
  8. {
  9. // 存在
  10. }
  11. else
  12. {
  13. // 不存在
  14. }
  15. }
  16. catch (Cartalyst\Sentry\Users\UserNotFoundException $e)
  17. {
  18. echo '用户不存在';
  19. }
  20. catch (Cartalyst\Sentry\Groups\GroupNotFoundException $e)
  21. {
  22. echo '管理员组不存在';
  23. }

权限到这讲完了,其实权限这个东西,没那么复杂,也不是需要多么高深的代码来实现,只是一种原理而已

扩展篇

我们上面学会了,怎么给用户权限,怎么检查权限,那么,问题来了,

我们需要在每个 action 里面,都检查用户权限吗 ?

答案是,不需要

  1. // 他会 获得当前访问的路由名称
  2. Route::currentRouteName()

我们可以在 filters.php 里面,

  1. // 获得当前登陆的用户
  2. $user = Sentry::getUser();
  3. $per = Route::currentRouteName();
  4. // 要检查多个权限需要使用一个数组来进行参数传递
  5. if ($user->hasAccess($per))
  6. {
  7. // 用户有权限访问当前的 action
  8. }
  9. else
  10. {
  11. // 没权限
  12. }

哈哈,这个东西手册里面可是没有哦,感谢 @ShineForce 的提醒,为了让大家可以偷下懒,特意去看了下 Route 的代码