首先要说明两点:1、 本文不是解决一个通用权限管理系统的方案,只是解决特定环境下的权限管理问题。本文给出的实际实现方法是基于sql server数据库的,实现的语言是使用T-Sql语言。当然您可以有更多的实现方式。2、 附件给出的数据库例子没有经过严格测试,不保证逻辑的正确性,以及性能方面的问题。
1、基于web信息管理系统的权限设计分析和总结(理论)
2、基于web信息管理系统的权限设计分析和总结(数据结构)
3、基于web信息管理系统的权限设计分析和总结(实现)
首先要说明两点:
1、 本文不是解决一个通用权限管理系统的方案,只是解决特定环境下的权限管理问题。本文给出的实际实现方法是基于sql server数据库的,实现的语言是使用T-Sql语言。当然您可以有更多的实现方式。
2、 附件给出的数据库例子没有经过严格测试,不保证逻辑的正确性,以及性能方面的问题。
首先需要一个存储过程来实现计算用户在表单上的权限,这个存储过程接受两个参数,用户ID和表单ID,在这个存储过程里面使用一条sql语句来计算用户在表单上的权限,如下所示:
Code
-- =============================================
--计算用户对表单的权限
-- =============================================
create PROCEDURE [dbo].[sp_GetUserPurveiewOnMenu]
@userID nvarchar(100) ,--用户ID
@formID nvarchar(100) --表单ID
AS
BEGIN
SELECT rp.formID,
u.userID,
--计算记录权限:只读记录
dbo.fun_Purview_GetRecordPurview(u.userID,rp.formID,'ReadOnlyRecords') as ReadOnlyRecords,
--计算记录权限:隐藏记录记录
dbo.fun_Purview_GetRecordPurview(u.userID,rp.formID,'HiddenRecord') as HiddenRecord,
--计算字段权限:只读记录(新增)
dbo.fun_Purview_GetColumns(u.userID,rp.formID,'ReadOnlyColumnsOnAdd') as ReadOnlyColumnsOnAdd,
--计算字段权限:隐藏记录(新增)
dbo.fun_Purview_GetColumns(u.userID,rp.formID,'HiddenColumnsOnAdd') as HiddenColumnsOnAdd,
--计算字段权限:只读记录(修改)
dbo.fun_Purview_GetColumns(u.userID,rp.formID,'ReadOnlyColumnsOnModify') as ReadOnlyColumnsOnModify,
--计算字段权限:隐藏记录(修改)
dbo.fun_Purview_GetColumns(u.userID,rp.formID,'HiddenColumnsOnModify') as HiddenColumnsOnModify,
--计算字段权限:隐藏记录(查询)
dbo.fun_Purview_GetColumns(u.userID,rp.formID,'HiddenColumnsOnSearch') as HiddenColumnsOnSearch,
--计算操作权限:新增
(CASE
WHEN (SUM((CAST((CASE f.AddAction WHEN 0 THEN 0
ELSE rp.AddAction
END) AS int)))) > 0
THEN cast(1 as bit)
ELSE cast(0 as bit)
END) as AddAction,
--计算操作权限:修改
(CASE
WHEN ( SUM((CAST((CASE f.ModifyAction WHEN 0 THEN 0
ELSE rp.ModifyAction
END) AS int))) ) > 0
THEN cast(1 as bit)
ELSE cast(0 as bit)
END) as ModifyAction,
--计算操作权限:删除
(CASE
WHEN ( SUM((CAST((CASE f.DeleteAction WHEN 0 THEN 0
ELSE rp.DeleteAction
END) AS int)))) > 0
THEN cast(1 as bit)
ELSE cast(0 as bit)
END) as DeleteAction,
--计算操作权限:查询
(CASE
WHEN ( SUM((CAST((CASE f.SearchAction WHEN 0 THEN 0
ELSE rp.SearchAction
END) AS int)))) > 0
THEN cast(1 as bit)
ELSE cast(0 as bit)
END) as SearchAction
FROM users u,
userinroles ur,
RolePurview rp,
forms f
WHERE u.userID = ur.userID
AND ur.roleID = rp.roleID
AND rp.formID = f.formID
AND u.userID = @userid
AND f.formID = @formID
GROUP BY rp.formID,u.userID
END
在这个存储过程里面,有两个用户函数,分别用于计算字段权限和记录权限。
用于计算字段权限的函数是fun_Purview_GetColumns,这个函数接受三个参数,分别是用户ID、表单ID和字段权限类型,具体如下所示:
Code
-- =============================================
-- 计算字段权限
-- =============================================
create FUNCTION [dbo].[fun_Purview_GetColumns]
(
@userID nvarchar(100),--用户ID
@formID nvarchar(100),--表单ID
@columnType varchar(50)--字段权限类型
)
RETURNS nvarchar(2000)
AS
BEGIN
declare @columsID nvarchar(4000),@tem nvarchar(1000),@c cursor
set @columsID=''
set @tem = ''
if @columnType = 'ReadOnlyColumnsOnAdd' -- 计算只读字段集合(新增)。对于其他字段集合类似
begin
set @c = cursor for select ReadOnlyColumnsOnAdd from forms where formID=@formID
union
select ReadOnlyColumnsOnAdd from RolePurview where roleID in(
select roleID from UserInRoles where userID=@userid
)
open @c
fetch next from @c into @tem
while @@fetch_status =0
begin
if @tem is not null
begin
set @columsID = @columsID +','+ @tem
end
fetch next from @c into @tem
end
close @c
deallocate @c
end
return @columsID
END
用于计算记录权限的函数是fun_Purview_GetRecordPurview,这个函数接受三个参数,分别是用户ID、表单ID和记录权限类型,具体如下所示:
Code
-- =============================================
--计算记录权限
-- =============================================
alter FUNCTION [dbo].[fun_Purview_GetRecordPurview]
(
@userid int,--用户ID
@formID int ,--表单ID
@recordPurviewType varchar(100)--记录权限类型
)
RETURNS nvarchar(4000)
AS
BEGIN
declare @recordPurviewSql nvarchar(4000),@c2 cursor,@sql nvarchar(4000),
@formRecordPurviewExpression nvarchar(4000)
set @recordPurviewSql = ''
set @sql = ''
if @recordPurviewType ='ReadOnlyRecords'--计算只读记录,对于隐藏记录类似
begin
set @c2 = cursor for select ReadOnlyRecords from RolePurivew where roleID in(
select roleID from UserInRoles where userID=@userid
) and formID=@formID
open @c2
fetch next from @c2 into @sql
while @@fetch_status =0
begin
if @sql is not null and @sql<> ''
begin
--对于角色之间的记录权限,使用并集
set @recordPurviewSql = @recordPurviewSql +'('+@sql+')' + ' or '
end
fetch next from @c2 into @sql
end
close @c2
deallocate @c2
if len(@recordPurviewSql) > 3
begin
set @recordPurviewSql = substring(@recordPurviewSql,1,len(@recordPurviewSql)-3)
end
select @formRecordPurviewExpression= ReadOnlyRecords from forms where formID=@formID
if @recordPurviewSql is not null and @recordPurviewSql <>''
begin
set @recordPurviewSql = '('+@recordPurviewSql+')'
if @formRecordPurviewExpression is not null and @formRecordPurviewExpression <>''
--对于角色和表单的记录权限,使用交集
set @recordPurviewSql = @recordPurviewSql +' and ('+@formRecordPurviewExpression+')'
end
else
begin
if @formRecordPurviewExpression is not null and @formRecordPurviewExpression <>''
set @recordPurviewSql = '('+@formRecordPurviewExpression+')'
end
end
return @recordPurviewSql
END
使用上面的函数就可以计算用户在表单上的权限了。
另外,您也可以对此权限模型进行扩展,比如您可以对角色设置一个角色的权限计算类型属性.
如果此角色是悲观型的,那么此角色和其他角色进行权限计算是,使用最小的权限集合。具体来说对于字段权限,使用与操作,对于字段权限和记录权限,使用交集。如果此角色是乐观型的,那么此角色和其他角色进行权限计算是,使用最大的权限集合。具体来说对于字段权限,使用或操作,对于字段权限和记录权限,使用并集。
在具体的项目实践中,为了提高性能,可以设置一些缓存,例如可以把上面的计算结果缓存到一个数据表里面,作为一级数据缓存。在程序中,还可以使用二级缓存在内存中保存用户的权限,当然这样做在提高性能的同时,也增加了程序的复杂度和数据的冗余,需要处理更多的地方。
最后,本文提供了一个可以执行的数据库备份,您可以点击此处下载。注意是sql2005的数据备份文件。