一种基于角色的用户访问控制方法主要是涉及数据库方面领域。
背景技术:
随着企业对信息系统越来越高的期望,传统的访问控制方法DAC(Discretionary Access Control,自主访问控制模型)、MAC(Mandatory Access Control,强制访问控制模型)已经难以满足复杂的企业环境需求。因此,90年代初美国国家标准化和技术委员会提出了基于角色的访问控制方法,该方法由于实现了用户与访问权限的逻辑分离,更加符合企业的用户、组织、数据和应用特征,而被越来越多的信息系统所使用。
基于角色的访问控制方法(RBAC-Role-Based Access Control)是目前公认的解决大型企业的统一资源访问控制的有效方法。其显著的两大特征是:
1.减小授权管理的复杂性,降低管理开销。
2.灵活地支持企业的安全策略,并对企业的变化有更大的伸缩性。
技术实现要素:
通过国家专利检索没有发现关于此系统方面的申请资料。
本文中使用Delphi作为开发工具来实现。在程序中,建立一个单元文件UFunctions.pas封装权限控制类,在系统登录时调用权限控制模块生成用户界面。此处仅列出主要的实现代码。
1.封装权限控制代码(UFunctions.pas)
//用户类
type
TUser = class(TObject)
private
_UserID: string;//用户代码
_UserName: string;//用户名
_PassWord: string;
public
constructor Create();
property UserID: string read _UserID;
property UserName: string read _UserName;
//登录用户
function Login(UserID, PassWord: string): Integer;
//注销用户
procedure Logout;
//修改密码
function ChangePassWord(OldPassWord, NewPassWord: string): boolean;
end;
//权限类
以下为权限定义部分:
type
TFunctions=class(TObject)
private
//整个菜单数据,功能号和窗体类的关联,用户可用的功能集
_cdsAllMenu,_cdsFunc,_cdsUserFunc: TClientDataSet;
_User:TUser;
//若子菜单有权限显示,必须把相应的父级菜单也显示出来
procedure ShowParentMenu(var cdsMenu:TClientDataSet;ParentMenuID:Integer); //显示子菜单,被ShowMenu调用
procedure ShowChildMenu(cdsMenu:TClientDataSet;MenuItem:TMenuItem;MenuID:Integer);
//显示菜单主过程
procedure ShowMenu(cdsMenu:TClientDataSet;Sender:TObject;mnuMain:TMainMenu); //显示工具栏按钮
procedure ShowToolButton(cdsUserFunc: TClientDataSet;tbMain:TToolBar);
//菜单点击动作处理程序
procedure MenuClick(Sender: TObject);
//根据窗体类名获得窗体类
function GetForm(FormName: string): TForm;
//传入窗体类名和窗体显示模式,创建该窗体类的一个实例
function ShowForm(FormName, FormModel: string): TForm;
function GetUser:TUser;
procedure SetUser(Value:TUser);
public
//登录用户的一个实例
property LoginUser:TUser read GetUser write SetUser;
//根据功能号执行相应的操作,若失败返回False
function ExeFunc(FuncID:String):Boolean;
//检查窗体的组件是否有权限,有则使之可用,否则禁用
procedure CheckFormChildFunc(Frm:TForm;FuncID:String);
//是否具有某权限
function HasRight(FuncID:String):Boolean;
//根据用户代码生成菜单和工具栏
procedure ShowMenuTool(UserID:String;var mnuMain:TMainMenu;
var tbMain:TToolBar;Sender:TObject);
//登录系统处理过程
function Login(UserID, PassWord: string): boolean;
end;
以下为一些关键的实现代码:
//根据功能号执行相应的操作,若失败返回False
function TFunctions.ExeFunc(FuncID:String):Boolean;
var
FormName, FormModel: string;
Frm:TForm;
begin
result:=False;
_cdsFunc.Filtered:=False;
_cdsFunc.Filter:='FuncID='''+FuncID+'''';
_cdsFunc.Filtered:=True;
//若该功能号不存在
if _cdsFunc.IsEmpty then
begin
_cdsFunc.Filtered:=False;
exit;
end;//if
if FuncID='1001' then//用户登录,该功能号是系统默认,1001表示的就是‘用户登录’功能。 else //打开窗体
begin
FormName:=_cdsFunc.FieldByName('ControlName').AsString;
FormModel:=_cdsFunc.FieldByName('FormModal').AsString;
_cdsFunc.Filtered:=False;
if FormName <> '' then
begin
Frm:=ShowForm(FormName, FormModel);
CheckFormChildFunc(Frm,FuncID);//控制窗体上的组件状态
end;
end;
_cdsFunc.Filtered:=False;
result:=True;
end;
//显示菜单
procedure TFunctions.ShowMenu(cdsMenu: TClientDataSet;
Sender: TObject;mnuMain:TMainMenu);
var
newMenu:TMenuItem;
cdsTmp:TClientDataSet;
FuncID:Integer;
begin
….
newMenu:=TMenuItem.Create(nil);
newMenu.Caption:='【'+cdsTmp.FieldByName('MenuText').AsString+'】';
FuncID:=GetIntDataSet(cdsTmp,'FuncID',0);
newMenu.Tag:=FuncID;
mnuMain.Items.Add(newMenu);
mnuMain.Items[mnuMain.Items.Count-1].Visible:=True;
if FuncID<>0 then newMenu.OnClick:=MenuClick;
ShowChildMenu(cdsMenu,newMenu,cdsTmp.FieldByName('MenuID').AsInteger);
……
end;
//传入窗体类名和显示模式,创建该窗体类的一个实例
function TFunctions.ShowForm(FormName, FormModel: string): TForm;
var
FormClass: TClass;
fForm: TForm;
bNull: Boolean;
begin
Result := nil;
bNull := False;
FormClass := GetClass(FormName);
FormModel := UpperCase(FormModel);
if FormClass = nil then
exit;
if (FormModel = 'M') or (FormModel = 'D') then
fForm := nil
else if (FormModel = 'S') then
fForm := GetForm(FormName)
else
exit;
if fForm = nil then
begin
Application.CreateForm(TComponentClass(FormClass), fForm); end
else
bNull := True;
if FormModel = 'D' then
begin
result := fForm;
fForm.ShowModal;
end
else
begin
fForm.Show;
result := fForm;
end;
ShowFuncIDInStatusBar(FuncID);
end;
2.主窗体部分,生成权限控制类的一个实例(UFrmMain)
var
MyFunctions: TFunctions;
MyFunctions := TFunctions.Create;
3.登录部分(UFrmLogin)
procedure TfrmLogin.btnLoginClick(Sender: TObject);
var
iRet,I:Integer;
sErr:String;
begin
iRet:=MyFunctions.LoginUser.Login(edtUserID.Text,edtPassWord.Text); Case iRet of
0:
sErr:='';
1:
sErr:='该账户已被禁用,请联系系统管理员!';
2:
sErr:='该账户密码已过期,请联系系统管理员!';
-1:
sErr:='用户密码有误,请重新输入!';
end;
//登录失败
if iRet<>0 then
begin
ShowMessage(sErr);
exit;
end
else//登录成功
begin
frmMain.Show;
MyFunctions.ShowMenuTool(MyFunctions.LoginUser.WorkID,frmMain.meuMain, frmMain.tbrMain,frmMain);
close;
end;
end;
4.定义一个窗体为功能时需要在该窗体中加入以下代码,使该窗体在系统中进行注册:
initialization
RegisterClass(TfrmTest);
TfrmTest是窗体的类名。
在‘功能定义’中可以这样登记:
功能号:2001
功能名称:测试功能
受控对象名:TfrmTest
窗体模式:S(S表示该窗体类仅能创建一个实例)。