博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
5.7. 用户/角色认证
阅读量:6655 次
发布时间:2019-06-25

本文共 3498 字,大约阅读时间需要 11 分钟。

本小节我们实现一个功能,当用户插入,修改或者删除数据时,判断该操作是否具备应有的权限。如果权限不符合就拒绝操作同时提示用户。

CREATE TABLE `staff` (	`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '员工ID',	`name` VARCHAR(50) NOT NULL COMMENT '员工名字',	PRIMARY KEY (`id`))COMMENT='员工表'COLLATE='utf8_general_ci'ENGINE=InnoDB;INSERT INTO `staff` (`id`, `name`) VALUES	(1, 'Neo'),	(2, 'Luke'),	(2, 'Jack');

staff 是员工表与下面的staff_has_role配合使用,形成员工与权限一对多关系。

CREATE TABLE `staff_has_role` (	`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,	`staff_id` INT(10) UNSIGNED NOT NULL COMMENT '员工ID',	`role` ENUM('Create','Update','Delete') NOT NULL COMMENT '角色',	PRIMARY KEY (`id`),	INDEX `FK_staff_has_role_staff` (`staff_id`),	CONSTRAINT `FK_staff_has_role_staff` FOREIGN KEY (`staff_id`) REFERENCES `staff` (`id`) ON UPDATE CASCADE ON DELETE CASCADE)COLLATE='utf8_general_ci'ENGINE=InnoDB;INSERT INTO `staff_has_role` (`id`, `staff_id`, `role`) VALUES	(1, 1, 'Create'),	(2, 1, 'Delete'),	(3, 1, 'Update'),	(4, 2, 'Delete'),	(5, 3, 'Create');	(6, 3, 'Update');

权限表可以进一步优化,角色拥有组功能,实现颗粒度更细的权限控制,有情趣看前面的相关章节。

CREATE TABLE `product` (	`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '唯一ID',	`name` VARCHAR(10) NOT NULL COMMENT '名称',	`sn` VARCHAR(10) NOT NULL COMMENT '序列号',	`price` FLOAT NOT NULL COMMENT '价格',	`amount` SMALLINT(6) NOT NULL COMMENT '数量',	`staff_id` INT(10) UNSIGNED NOT NULL COMMENT '员工ID',	`ctime` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',	`mtime` TIMESTAMP NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',	PRIMARY KEY (`id`),	UNIQUE INDEX `sn` (`sn`),	INDEX `FK_product_staff` (`staff_id`),	CONSTRAINT `FK_product_staff` FOREIGN KEY (`staff_id`) REFERENCES `staff` (`id`))COMMENT='产品表'COLLATE='utf8_general_ci'ENGINE=InnoDB;

以产品表为例,这里要实现的是对产品表记录的权限控制。例如Neo有用插入,修改和删除权限,Luke的Create与Update权限被吊销,只能删除他之前创建的数据。而Jack只有能创建于更新数据。

下面的三个触发器完成具体的权限控制。同样你可以进一步优化下面的代码的权限颗粒度,使之能控制到具体列,甚至具体的记录。

CREATE DEFINER=`root`@`%` TRIGGER `product_before_delete` BEFORE DELETE ON `product` FOR EACH ROW BEGIN	if not exists(select id from staff where id=OLD.staff_id and role="delete") then		SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Permission denied', MYSQL_ERRNO = 1001;	end if;ENDCREATE DEFINER=`root`@`%` TRIGGER `product_before_insert` BEFORE INSERT ON `product` FOR EACH ROW BEGIN	 if not exists(select id from staff where id=NEW.staff_id and role="create") then	       SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = "The staff's role is not correct or it does not exist.", MYSQL_ERRNO = 1001;	 end if;ENDCREATE DEFINER=`root`@`%` TRIGGER `product_before_update` BEFORE UPDATE ON `product` FOR EACH ROW BEGIN	if not exists(select id from staff where id=NEW.staff_id and role="update") then		SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = "The staff's role cannot update data.", MYSQL_ERRNO = 1001;	end if;END

Neo 测试如下

INSERT INTO `test`.`product` (`name`, `sn`, `price`, `amount`, `staff_id`, `ctime`) VALUES ('Iphone', '678624', '5000', '77', '1', '2010-08-18 15:38:23');SELECT LAST_INSERT_ID();UPDATE `test`.`product` SET `name`='HTC', `sn`='5544467', `price`='2000' WHERE  `id`=2;DELETE FROM `test`.`product` WHERE  `id`=1;

Luke 测试如下:

INSERT INTO `test`.`product` (`name`, `sn`, `price`, `amount`, `staff_id`) VALUES ('Nokia', '65722', '800', '55', '2');/* SQL错误(1001):The staff's role is not correct or it does not exist. */UPDATE `test`.`product` SET `name`='HTC', `sn`='5544467', `price`='2000', staff_id=2 WHERE  `id`=2;/* SQL错误(1001):The staff's role cannot update data. */

原文出处:Netkiller 系列 手札

本文作者:陈景峯
转载请与作者联系,同时请务必标明文章原始出处和作者信息及本声明。

你可能感兴趣的文章
线程组
查看>>
涉密数据的处理
查看>>
我的友情链接
查看>>
【单机实现系列】通过scom2012对Hyper-V主机来监控和邮件报警②
查看>>
16.文件系统——软RAID的实现(三)(RAID5、装配RAID、JBOD)
查看>>
python简介
查看>>
python字典开发三级菜单
查看>>
.net Framework下载地址
查看>>
十三个经典算法集锦
查看>>
关于rsync报错的问题
查看>>
深圳偶遇
查看>>
给自己电脑安装SSD与加内存条
查看>>
国内最大的 Node.js 社区将 New Relic 的监控产品换成了 OneAPM
查看>>
如何有效地记录 Java SQL 日志?
查看>>
学习Linux决心书
查看>>
stp 总结
查看>>
Java本地文件操作(五)遍历文件夹
查看>>
BGP学习笔记
查看>>
mysql字段加密
查看>>
linux 磁盘分区(一)
查看>>