要在codeigniter中实现真正的角色路由控制,必须将角色判断嵌入请求生命周期前端:登录时存role_id到会话,用filter拦截并校验路径白名单(支持通配符),通过路由分组或permission标签绑定权限,在routes.php中动态注册允许的路由。

要在CodeIgniter中让路由真正按用户角色生效,不能只靠URL映射,必须把角色判断嵌入请求生命周期前端——否则任何人都能手动拼出后台URL绕过权限。
先确认角色信息已加载到会话
登录成功后,务必把用户角色ID(或角色标识符)存入CI会话,且不可仅存用户名或ID。因为权限校验依赖角色,不是用户个体。
【必须确保】在登录逻辑中执行:$this->session->set_userdata('role_id', $user_role_id);,而不是只存user_id。
若跳过这步,后续所有路由权限控制都将失效——系统根本不知道当前是谁、属于什么角色。
用Filter拦截请求并校验角色(CI4推荐方式)
这是最干净、最可控的实现路径,避免在每个控制器里重复写权限判断。
第一步:在app/Filters/RoleFilter.php中创建过滤器类,继承FilterInterface;
第二步:在before()方法中获取会话中的role_id,查询该角色被允许访问的route_pattern列表(从数据库或缓存读取);
第三步:用$request->getUri()->getPath()拿到当前请求路径,与白名单比对;不匹配则返回redirect()->to('access-denied')或抛出HTTP 403异常。
注意:白名单规则必须支持通配符,例如admin/*、api/v1/users/*,否则编辑角色无法批量授权子路径。
在routes.php中绑定角色组与路由组
不建议直接在routes.php里硬编码角色判断,但可以预定义路由命名空间,为Filter提供语义标签。
方法一:用路由分组标记角色域
$routes->group('admin', ['filter' => 'role:admin'], function($routes) {
$routes->add('dashboard', 'Admin::dashboard');
$routes->add('users/edit/(:num)', 'Admin::editUser/$1');
});
这里的role:admin是Filter参数,实际校验逻辑仍在RoleFilter.php中解析——CI4的filter机制支持冒号传参,比写死条件更灵活。
方法二:给关键路由加别名并关联权限码
$routes->add('posts/create', 'Posts::create', ['permission' => 'post.create']);
随后在Filter中根据permission字段查角色-权限关联表,比路径匹配更精确,也便于后期接入RBAC模型。
动态路由权限匹配(适用于菜单驱动型后台)
当菜单项和权限点来自数据库时,需在路由注册阶段就完成角色能力注入。
① 在app/Config/Routes.php顶部,手动加载当前登录角色的可访问路由数组:
$allowed_routes = service('role_permission')->getAllowedRoutes(session('role_id'));
② 遍历$allowed_routes,逐条调用$routes->add(...)注册——未在此列表中的路径根本不会被CI识别,自然404。
③ 关键点:此操作必须在$routes->setAutoRoute(false)之后、任何add()之前执行,否则自动路由会覆盖手动注册的权限路径。
这一步会让未授权路径彻底不可达,连路由解析环节都跳过,比运行时拦截更早、更安全。










