我正在编写一个具有用户登录功能的GUI应用程序。每个用户将属于(至少一个,可能多于一个)组,并且每个组将具有指示是否允许某些权限的属性。权限列表将涵盖诸如过去编辑事物,打印,删除数据等内容。可以通过相同的权限处理许多不同的操作(例如,可以从菜单和工具栏中启动打印)。
我的问题是:实施此安全系统的最佳方法是什么?每个操作都应该有一个布尔的isSecurable属性和所需的权限列表吗?如何通过中央结构进行检查,或者每个行动应该检查所需权利本身?
我的目标是正确性。我知道我可以迅速将一个工作系统整合在一起,但我希望能有一些不会在未来出现问题的东西。对于冗长的解释我很抱歉,但我甚至不确定该怎么称呼我。
编辑:我认为这不是特定于GUI的,但我已经对此进行了大量研究,我发现大多数内容都是针对Web应用程序或一般的“安全编程”提示。 / p>
答案 0 :(得分:3)
“BCS”是正确的,安全检查不应该绑定到GUI,应该绑定到您正在调用的基础操作/操作/方法。在MVC框架中,它将在模型或其他地方的模型调用的操作中。
如果您的行为的发送肯定会通过一些共同的机制(例如,所有共享某个基类),那么在那里进行安全检查是一种很好的方式来覆盖所有基础。
另外一个想法:你所描述的群体在安全术语中可能是也可能不是“角色”。
答案 1 :(得分:1)
我会使用类似MVC系统的东西,并且不会在GUI代码中放入任何安全性内容。使其成为模型的一部分,以便它不会影响用户触发操作的方式,运行相同的安全代码路径。
我从来没有做过太多的GUI甚至更少的安全性,但一种方法是拥有一个安全的代理对象来跟踪谁登录并且仅转发当前上下文中允许的请求。
如果你想要一个有趣的项目,那个代理对象将是生成代码的理想选择:
给定一个带有安全注释的接口,生成一个实现该接口的类,并根据传递给它的安全上下文阻塞/转发调用。
答案 2 :(得分:1)
如果您要编写.NET应用程序,可以考虑使用成员资格提供程序基础结构。您甚至可以使用此方法为Web和桌面客户端实施身份验证,如this MSDN magazine article中所述。
答案 3 :(得分:0)
您的问题听起来像状态模式。用户所属的每个组都是不同的State Object。将每个适用的State Object附加到用户。然后,当用户尝试执行需要权限的操作时,请询问状态对象。
由于用户可以在多个组中,因此您也可以从装饰器模式中受益。
答案 4 :(得分:0)
我知道这是一个老帖子,但想提供我的解决方案。它可能不是最好的方法,但它对我有用,可能对某人有用。
我有一个用Delphi 7编写的数据库应用程序(Windows GUI和MySQL)。
应用程序的管理员可以创建具有不同访问级别的用户。该应用程序管理工厂生产(原材料),产品,销售和服务,以及在3个国家拥有工厂和办事处的公司的会计。
用户可以根据自己的安全权限访问标签,表格和功能。
基本上,某些功能可以根据权限禁用或隐藏。在某些情况下,我会向用户显示一条消息,有时如果他们的权利不够,则会忽略他们的行为。每个用户可以拥有单个权限或权限组合。
例如,某人可能有;
就像这样;
unit bitwise; // Found this unit on stackoverflow - All credit to original author
interface
Const // Added constants that suit me
Adm = 01; // Administrator
Rws = 02; // Read Write Sales
Ros = 04; // Read Only Sale
Rwp = 08; // Read Write Production
Rop = 16; // Read Only Production
roa = 32; // Read Only All
acc = 64; // Accounting
function IsBitSet(const val: byte; const TheBit: Byte): Boolean;
function BitOn(const val: byte; const TheBit: Byte): byte;
function BitOff(const val: byte; const TheBit: Byte): byte;
function BitToggle(const val: byte; const TheBit: Byte): byte;
implementation
function IsBitSet(const val: byte; const TheBit: Byte): Boolean;
begin
Result := (val and (TheBit)) <> 0;
end;
function BitOn(const val: byte; const TheBit: Byte): byte;
begin
Result := val or (TheBit);
end;
function BitOff(const val: byte; const TheBit: Byte): byte;
begin
Result := val and not (TheBit);
end;
function BitToggle(const val: byte; const TheBit: Byte): byte;
begin
Result := val xor (TheBit);
end;
end. // End of Unit
如果我想在用户尝试无法访问的内容时显示消息,请使用以下功能。
Function TForm1.HasRights(Need: Byte; Msg: String;): Boolean;
Begin
If Not IsBitSet(rights, Need) Then
Begin
showdialog('Security', 'You have insufficient Security Rights!', 'You must have ' +
Msg + ' access to perform the action you have attempted.', '', '', false, False, True);
Result := False;
End
Else
Result := True;
End;
我这样称呼上述功能;
If HasRights(Rop Or Rwp Or Adm, '"Read Only Production" or "Read / Write Production"') Then
Begin
// Do something they are allowed to do
End // else ignore them
如果我不需要显示消息框,我会像这样调用IsBitSet;
If IsBitSet(rights, Adm) Then
Begin
// Do stuff
end;
仅为清晰度,这是 ShowDialog功能。它显示了我创建的自定义表单,非常适合我的应用程序。
Function TForm1.showdialog(Const DialogTitle: WideString; Const FirstCaption: WideString;
Const SecondCaption: widestring; Const ConfirmBCaption: widestring; Const CancelBCaption:
widestring; LeftButton, RightButton, MiddleButton: Boolean): boolean;
Var
whattheysaid: boolean;
craigsdialog: Tcraigsdialog;
Begin
// Modal1Button and Modal2Button can have modified captions whereas Modal3Button
// is always "Ok". If the only button a user needs is "Ok" then make it visible
// and receive a modalresult of 3 when clicked. This 3rd button is for appearance
// only and just makes it a bit neater.
Whattheysaid := False;
Craigsdialog := Tcraigsdialog.Create(nil);
With Craigsdialog Do
Begin
// Set the Dialog details as required
Caption := DialogTitle;
Label1.Caption := FirstCaption;
Label2.Caption := SecondCaption;
Modal1Button.Visible := leftbutton;
Modal2Button.Visible := rightbutton;
Modal3Button.Visible := Middlebutton;
modal1button.Caption := ConfirmBCaption;
modal2button.Caption := CancelBCaption;
Case ShowModal Of
1: whattheysaid := True
2: whattheysaid := False
3: whattheysaid := True
End;
End;
FreeAndNil(craigsdialog);
Result := whattheysaid;
End;
正如我所说,这可能有用也可能没用,但它对我来说非常有用。