Linux中ThinkPHP权限控制
导读:Linux下 ThinkPHP 权限控制实践 一 概念与总体架构 在 Linux 部署 ThinkPHP,权限控制通常包含两类: 系统层面:文件和目录的访问权限与属主/属组,确保 Web 服务进程对缓存、日志等可写目录具备写入能力,同时...
Linux下 ThinkPHP 权限控制实践
一 概念与总体架构
- 在 Linux 部署 ThinkPHP,权限控制通常包含两类:
- 系统层面:文件和目录的访问权限与属主/属组,确保 Web 服务进程对缓存、日志等可写目录具备写入能力,同时避免对敏感目录的非法访问。
- 应用层面:基于 RBAC(基于角色的访问控制) 的用户-角色-权限模型与中间件校验,控制控制器/方法的访问。
- 推荐的数据表结构:users / roles / permissions / user_roles / role_permissions,通过中间件在请求进入控制器前进行鉴权与放行。
二 系统层面目录权限与安全防护
- 基本思路
- 将站点目录的所有者设为部署用户(如:demo),所属组设为 Web 服务运行用户(如 www-data 或 apache),再按“目录 750、文件 640”收紧权限,仅对需要写入的目录单独放宽。
- 对 runtime 等需要写入的目录,递归设置为 770,保证进程可写;同时禁止通过浏览器直接访问敏感目录与 PHP 文件。
- 示例命令(以 Ubuntu/Apache 为例,Web 运行用户为 www-data,站点目录为 /var/www/html/demo)
# 1) 调整属主/属组 chown -R demo:www-data /var/www/html/demo # 2) 目录 750,文件 640 find /var/www/html/demo -type d -exec chmod 750 { } \; find /var/www/html/demo -not -type d -exec chmod 640 { } \; # 3) 对需要写入的目录(如 runtime、上传目录)放宽到 770 find /var/www/html/demo -name "runtime" -type d -exec chmod -R 770 { } \; # 如有上传目录:find /var/www/html/demo -name "upload" -type d -exec chmod -R 770 { } \; - 禁止访问敏感目录(Apache)
- 在 runtime/.htaccess 中加入:
Order Allow,Deny Deny from all - 或在项目根目录的 .htaccess 中限制访问 config/ 与 runtime/ 下的 .php 文件:
< FilesMatch "\.php$"> Order deny,allow Deny from all < /FilesMatch> < FilesMatch "^(.*)/config/.*\.php$"> Order deny,allow Deny from all < /FilesMatch> < FilesMatch "^(.*)/runtime/.*\.php$"> Order deny,allow Deny from all < /FilesMatch>
- 在 runtime/.htaccess 中加入:
- 安全提醒
- 避免使用 chmod 777 -R,这会放宽所有用户权限,存在重大安全风险。
- 若使用 Nginx+PHP-FPM,需将 PHP-FPM 运行用户/组与目录属组保持一致(如同为 www-data),否则会出现写入失败。
三 应用层面 RBAC 与中间件实现
- 数据表设计(示例)
CREATE TABLE `users` ( `id` int(11) NOT NULL AUTO_INCREMENT, `username` varchar(50) NOT NULL, `password` varchar(255) NOT NULL, PRIMARY KEY (`id`) ); CREATE TABLE `roles` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(50) NOT NULL, PRIMARY KEY (`id`) ); CREATE TABLE `permissions` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(50) NOT NULL, `action` varchar(100) NOT NULL, -- 如:admin/user/list PRIMARY KEY (`id`) ); CREATE TABLE `user_roles` ( `user_id` int(11) NOT NULL, `role_id` int(11) NOT NULL, PRIMARY KEY (`user_id`,`role_id`) ); CREATE TABLE `role_permissions` ( `role_id` int(11) NOT NULL, `permission_id` int(11) NOT NULL, PRIMARY KEY (`role_id`,`permission_id`) ); - 中间件示例(认证 + 权限校验)
// app/middleware/Auth.php namespace app\middleware; use think\Request; use think\facade\Session; use app\model\User; use app\model\Role; use app\model\Permission; class Auth { // 无需校验的白名单(如登录、验证码) protected $whiteList = ['login', 'captcha']; public function handle(Request $request, \Closure $next) { $controllerAction = strtolower($request-> controller() . '/' . $request-> action()); if (in_array($controllerAction, $this-> whiteList, true)) { return $next($request); } $userId = Session::get('user_id'); if (!$userId) { return redirect('/login'); } $user = User::with(['roles.permissions'])-> find($userId); if (!$user) { Session::delete('user_id'); return redirect('/login'); } // 将用户与权限注入到请求,便于控制器/视图使用 $request-> user = $user; $perms = []; foreach ($user-> roles as $role) { foreach ($role-> permissions as $perm) { $perms[$perm-> action] = true; } } $request-> userPerms = $perms; // 校验当前请求是否在用户权限中 if (!isset($perms[$controllerAction])) { return json(['code' => 403, 'msg' => '无权限'], 403); } return $next($request); } } - 在路由或控制器中应用中间件
// 全局应用(示例) // 或者在需要保护的路由组/控制器构造中绑定中间件 - 登录示例(简化)
// app/controller/Index.php public function login() { $username = $this-> request-> param('username'); $password = $this-> request-> param('password'); $user = User::where('username', $username)-> find(); if ($user & & password_verify($password, $user-> password)) { Session::set('user_id', $user-> id); return json(['status' => 'success', 'message' => '登录成功']); } return json(['status' => 'error', 'message' => '用户名或密码错误']); } - 扩展
- 可按需引入 ABAC(基于属性:时间、IP、设备等)或细粒度到“按钮/接口”的权限判断。
四 常见问题与排查
- 出现“日志/缓存写入失败”
- 检查 runtime 目录及其子目录对 Web 运行用户是否可写(属主/属组是否正确,权限是否 ≥ 770)。
- 若使用 Nginx+PHP-FPM,确认 PHP-FPM 的 user/group 与目录属组一致。
- 浏览器能直接访问 runtime 下的敏感文件
- 在 runtime/.htaccess 中写入“Deny from all”,或在根目录 .htaccess 限制 config/、runtime/ 的 .php 访问。
- 使用 chmod 777 后仍有写入问题
- 多数为 SELinux 或 open_basedir 限制,检查并调整策略或关闭相关限制(生产环境不建议直接关闭,应精细化策略)。
- 部署脚本批量设置权限
- 可编写脚本对多个项目统一设置 Runtime 目录权限,但务必避免对整站使用 777。
声明:本文内容由网友自发贡献,本站不承担相应法律责任。对本内容有异议或投诉,请联系2913721942#qq.com核实处理,我们将尽快回复您,谢谢合作!
若转载请注明出处: Linux中ThinkPHP权限控制
本文地址: https://pptw.com/jishu/761888.html
