上一篇
场景引入:
想象一下,你刚开发了一个企业后台管理系统,结果实习生误删了生产数据库,或者市场部的同事看到了财务部的敏感数据……这种混乱的场面,往往源于权限管理的缺失,我们就用PHP手把手实现一套既安全又灵活的登录认证与权限控制系统。
-- 用户表 CREATE TABLE `users` ( `id` INT AUTO_INCREMENT PRIMARY KEY, `username` VARCHAR(50) UNIQUE NOT NULL, `password` VARCHAR(255) NOT NULL, -- 存储bcrypt哈希值 `email` VARCHAR(100) UNIQUE NOT NULL, `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); -- 角色表 CREATE TABLE `roles` ( `id` INT AUTO_INCREMENT PRIMARY KEY, `name` VARCHAR(30) UNIQUE NOT NULL -- 如:admin, editor, viewer ); -- 用户-角色关联表 CREATE TABLE `user_roles` ( `user_id` INT NOT NULL, `role_id` INT NOT NULL, PRIMARY KEY (`user_id`, `role_id`), FOREIGN KEY (`user_id`) REFERENCES `users`(`id`), FOREIGN KEY (`role_id`) REFERENCES `roles`(`id`) ); -- 权限表(RBAC模型) CREATE TABLE `permissions` ( `id` INT AUTO_INCREMENT PRIMARY KEY, `code` VARCHAR(50) UNIQUE NOT NULL, -- 如:create_post `description` VARCHAR(200) NOT NULL ); -- 角色-权限关联表 CREATE TABLE `role_permissions` ( `role_id` INT NOT NULL, `permission_id` INT NOT NULL, PRIMARY KEY (`role_id`, `permission_id`) );
// 注册时密码加密 function hashPassword($plainPassword) { return password_hash($plainPassword, PASSWORD_BCRYPT, ['cost' => 12]); } // 登录验证 function verifyPassword($inputPassword, $hashedPassword) { return password_verify($inputPassword, $hashedPassword); }
class Auth { private $db; public function __construct($dbConnection) { $this->db = $dbConnection; session_start(); } // 用户登录 public function login($username, $password) { $stmt = $this->db->prepare("SELECT id, password FROM users WHERE username = ?"); $stmt->execute([$username]); $user = $stmt->fetch(PDO::FETCH_ASSOC); if ($user && verifyPassword($password, $user['password'])) { $_SESSION['user_id'] = $user['id']; return true; } return false; } // 检查是否登录 public function isLoggedIn() { return isset($_SESSION['user_id']); } // 获取当前用户角色 public function getUserRoles() { if (!$this->isLoggedIn()) return []; $stmt = $this->db->prepare(" SELECT r.name FROM roles r JOIN user_roles ur ON r.id = ur.role_id WHERE ur.user_id = ? "); $stmt->execute([$_SESSION['user_id']]); return $stmt->fetchAll(PDO::FETCH_COLUMN, 0); } }
// 权限检查中间件 function hasPermission($requiredPermission) { $auth = new Auth($db); if (!$auth->isLoggedIn()) return false; $stmt = $db->prepare(" SELECT COUNT(*) FROM role_permissions rp JOIN permissions p ON rp.permission_id = p.id JOIN user_roles ur ON rp.role_id = ur.role_id WHERE ur.user_id = ? AND p.code = ? "); $stmt->execute([$_SESSION['user_id'], $requiredPermission]); return $stmt->fetchColumn() > 0; } // 使用示例:删除文章前检查权限 if (!hasPermission('delete_post')) { die('抱歉,您没有删除权限'); }
// 根据权限生成导航菜单 function generateMenu() { $menuItems = [ ['label' => '仪表盘', 'permission' => 'view_dashboard'], ['label' => '内容管理', 'permission' => 'manage_content'], ['label' => '用户管理', 'permission' => 'manage_users'] ]; $output = '<ul>'; foreach ($menuItems as $item) { if (hasPermission($item['permission'])) { $output .= "<li>{$item['label']}</li>"; } } $output .= '</ul>'; return $output; }
// 生成CSRF令牌 function generateCsrfToken() { if (empty($_SESSION['csrf_token'])) { $_SESSION['csrf_token'] = bin2hex(random_bytes(32)); } return $_SESSION['csrf_token']; }
// 验证表单提交 if ($_POST['csrf_token'] !== $_SESSION['csrf_token']) { die('非法请求'); }
2. **登录失败限制**
```php
// 记录失败尝试
if ($loginFailed) {
$cacheKey = "login_attempts_{$_SERVER['REMOTE_ADDR']}";
$attempts = $cache->get($cacheKey) ?: 0;
$cache->set($cacheKey, ++$attempts, 3600); // 1小时限制
if ($attempts > 5) {
die('尝试次数过多,请稍后再试');
}
}
-- 记录关键操作 CREATE TABLE `audit_logs` ( `id` INT AUTO_INCREMENT PRIMARY KEY, `user_id` INT NOT NULL, `action` VARCHAR(100) NOT NULL, -- 如:delete_user `ip_address` VARCHAR(45) NOT NULL, `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP );
:这套方案实现了:
根据2025年的安全实践建议,建议每季度进行一次权限复核,并始终使用预处理语句防止SQL注入。
本文由 么念巧 于2025-08-02发表在【云服务器提供商】,文中图片由(么念巧)上传,本平台仅提供信息存储服务;作者观点、意见不代表本站立场,如有侵权,请联系我们删除;若有图片侵权,请您准备原始证明材料和公证书后联系我方删除!
本文链接:https://vps.7tqx.com/wenda/512439.html
发表评论