我可以建议两种可能的更改……和一条评论。
首先,将您的原始支票尽可能地推到链条上。抛出异常以传达授权错误。
void readBook (Book &book)
{
// readbook doesn't need to perform any checks of it's own.
// the more primitive actions will scream and yell if the user
// isn't allowed to perform sub-action X.
openBook(book);
BookData d = getBookData(book);
// etc.
}
void openBook (Book &book)
{
if (!checkSecurity (book, OPENBOOK))
throw new SecurityException("User X is not allowed to open this book!");
// etc.
}
BookData getBookData (Book &book)
{
if (!checkSecurity (book, SEEBOOK))
throw new SecurityException("User X is not allowed to read this book's data!");
// etc.
}
其次,将您的安全行动映射到实际行动。如果您愿意,您甚至可以在数据中执行此操作。例如 ...
class Security {
// this check get tricky.
// if an "real action" isn't listed anywhere, does the user have implicit permission?
// (i'm assuming not, for this example.)
public static Check(String realAction, Boolean requireAll = true) {
Int32 required = 0;
Int32 userHas = 0;
foreach (KeyValuePair<String, List<String>> pair in Actions) {
if (pair.Value.Contains(realAction))
{
required++;
if (Security.CurrentUser.Actions.Contains(pair.Key))
{
userHas++;
}
}
}
if (requireAll)
{
return userHas > 0 && userHas == required;
}
else
{
return userHas > 0;
}
}
// hardcoded here, but easily populated from a database or config file
public static Dictionary<String, List<String>> Actions {
{"OpenBook", new List<String>() { "readBook", "writeBook" }},
{"SeeBook", new List<String>() { "readBook", "writeBook" }}
}
}
void readBook(Book &book) {
if (!Security.Check("readBook")) return false;
// etc.
}
这里的Check()
方法接受一个requireAll
参数,但映射本身可以很容易地更新为“坚持”或“偏好”存在于它们隐含的“真实动作”中。
我的评论是:不要过度详细说明您的安全性。一些安全规则暗示了其他规则,这些规则本身可能没有意义。例如,READBOOK
andWRITEBOOK
都暗示了一种能力OPENBOOK
,并且OPENBOOK
可能本身没有意义。虽然对于用户来说,能够OPENBOOK
或WRITEBOOK
没有诸如SEEBOOKCOVER
and之类的东西可能看起来很愚蠢SEEBOOKINSEARCHRESULTS
,但我建议在读书时唯一相关的权限是READBOOK
.