安全系统策略
XAF的安全系统是用静态类SecuritySystem定义的。终端用户使用XAF程序时,安全系统会检查当前用户是否有足够的权限执行某项操作。
XAF提供了两个内置安全策略:
Simple Security Strategy
该策略有两个用户类型:用户(user)和管理员(administrator)。user可以访问除User对象外的所有对象。然而,它可以修改自身的密码和其他安全无关的详情。此外,user可以在只读模式下访问User列表。Administrator可以访问全部的对象,此外还可以编辑Application Model。
Complex Security Strategy
该策略提供了多种用户组,这些组被叫做Role。每个组拥有不同的权限,用户user可以拥有多个Role,即用户的权限可以叠加。user和role的关系是多对多的关系。
XAF的两种认证方式:
Standard Authentication
标准认证。弹出登录窗口,输入用户名和密码登录。
Active Directory Authentication
活动文件夹认证。程序使用WindowsActiveDirectory服务获取用户信息,然后使用该信息验证用户。若在当前系统找到用户和数据库的对象符合,则通过验证。XAF默认使用这种方式验证。
Complex Security Strategy
1.基本概念
五种操作权限:
SecurityOperations.Create
SecurityOperations.Delete
SecurityOperations.Navigation
SecurityOperations.Read
SecurityOperations.Write
这里要说一下的是SecurityOperations.Navigation权限,当针对的是Type时,表示在导航栏和列表可导航,当针对的是object时,在导航栏不可见,但在列表中可导航。
精细的权限控制,三种权限控制级别:
object-level: 针对具体的对象,一般需要设置对象筛选;
type-level: 针对某种类型,其子类当然也属于该权限范围;
member-level:针对某类型的属性(成员);
三种权限可以组合,构成复杂的权限。
2.实现步骤
2.1 加入安全Model
将Security Strategy Complex和Authentication Standard拖到 WinApplication.cs中。
以下代码需要加入到MySolution.Module | DatabaseUpdate | Updater.cs的UpdateDatabaseAfterUpdateSchema方法中。另外,其中用到的两个自定义函数如下,他们也位于该文件中:
private void GrantAllAccess(Type type, ref SecurityRole role)
{
role.Permissions.GrantRecursive(type, SecurityOperations.Create);
role.Permissions.GrantRecursive(type, SecurityOperations.Delete);
role.Permissions.GrantRecursive(type, SecurityOperations.Navigate);
role.Permissions.GrantRecursive(type, SecurityOperations.Read);
role.Permissions.GrantRecursive(type, SecurityOperations.Write);
}
private void DenyAllAccess(Type type, ref SecurityRole role)
{
role.Permissions.DenyRecursive(type, SecurityOperations.Create);
role.Permissions.DenyRecursive(type, SecurityOperations.Delete);
role.Permissions.DenyRecursive(type, SecurityOperations.Navigate);
role.Permissions.DenyRecursive(type, SecurityOperations.Read);
role.Permissions.DenyRecursive(type, SecurityOperations.Write);
}
2.2 创建各Role和User
#region 创建Administrator Role
// If a role with the Administrators name does not exist in the database, create this role
SecurityRole adminRole = ObjectSpace.FindObject<SecurityRole>(new BinaryOperator("Name", "Administrators"));
if (adminRole == null)
{
adminRole = ObjectSpace.CreateObject<SecurityRole>();
adminRole.Name = "Administrators";
}
adminRole.BeginUpdate();
//Give a permission to edit the Application Model
adminRole.CanEditModel = true;
//Provide full access to all objects
GrantAllAccess(typeof(object), ref adminRole);
adminRole.EndUpdate();
//Save the Administrators role to the database
adminRole.Save();
#endregion
#region 创建User Role,从Administrator中减少权限
// If a role with the "Users" name doesn't exist in the database, create this role
SecurityRole userRole = ObjectSpace.FindObject<SecurityRole>(new BinaryOperator("Name", "Users"));
if (userRole == null)
{
userRole = ObjectSpace.CreateObject<SecurityRole>();
userRole.Name = "Users";
}
userRole.BeginUpdate();
GrantAllAccess(typeof(object), ref userRole);
DenyAllAccess(typeof(SecurityUser), ref userRole);
DenyAllAccess(typeof(SecurityRole), ref userRole);
DenyAllAccess(typeof(PermissionDescriptorBase), ref userRole);
DenyAllAccess(typeof(PermissionData), ref userRole);
DenyAllAccess(typeof(TypePermissionDetails), ref userRole);
userRole.EndUpdate();
// Save the "Users" role to the database
userRole.Save();
#endregion
SecurityRole defaultRole = ObjectSpace.FindObject<SecurityRole>(new BinaryOperator("Name", "Default"));
if (defaultRole == null)
{
defaultRole = ObjectSpace.CreateObject<SecurityRole>();
defaultRole.Name = "Default";
//object-level控制,针对Oid为当前用户id的SecurityUser对象
//Allow reading and navigating to the SecurityUser object representing the current user
ObjectOperationPermissionData myDetailsPermission = ObjectSpace.CreateObject<ObjectOperationPermissionData>();
myDetailsPermission.TargetType = typeof(SecurityUser);
myDetailsPermission.Criteria = "[Oid] = CurrentUserId()";
myDetailsPermission.AllowNavigate = true;
myDetailsPermission.AllowRead = true;
myDetailsPermission.Save();
defaultRole.PersistentPermissions.Add(myDetailsPermission);
//Member-level控制,针对SecurityUser的ChangePasswordOnFirstLogon和StoredPassword属性
//Allow an access to change the ChangePasswordOnFirstLogon and StoredPassword properties of the
MemberOperationPermissionData userMembersPermission = ObjectSpace.CreateObject<MemberOperationPermissionData>();
userMembersPermission.TargetType = typeof(SecurityUser);
userMembersPermission.Members = "ChangePasswordOnFirstLogon, StoredPassword";
userMembersPermission.AllowWrite = true;
userMembersPermission.Save();
defaultRole.PersistentPermissions.Add(userMembersPermission);
//Allow reading and navigating to the SecurityRole object representing the current Role
ObjectOperationPermissionData defaultRolePermission = ObjectSpace.CreateObject<ObjectOperationPermissionData>();
defaultRolePermission.TargetType = typeof(SecurityRole);
defaultRolePermission.Criteria = "[Name] = 'Default'";
defaultRolePermission.AllowNavigate = true;
defaultRolePermission.AllowRead = true;
defaultRolePermission.Save();
defaultRole.PersistentPermissions.Add(defaultRolePermission);
//Type-level控制,针对AuditDataItemPersistent类型
//Allow access to the objects of the AuditDataItemPersistent type
TypeOperationPermissionData auditDataItemPermission = ObjectSpace.CreateObject<TypeOperationPermissionData>();
auditDataItemPermission.TargetType = typeof(AuditDataItemPersistent);
auditDataItemPermission.AllowRead = true;
auditDataItemPermission.AllowWrite = true;
auditDataItemPermission.AllowCreate = true;
auditDataItemPermission.Save();
defaultRole.PersistentPermissions.Add(auditDataItemPermission);
defaultRole.Save();
}
SecurityUser user1 = ObjectSpace.FindObject<SecurityUser>(new BinaryOperator("UserName", "Sam"));
if (user1 == null)
{
user1 = ObjectSpace.CreateObject<SecurityUser>();
user1.UserName = "Sam";
// Set a password if the standard authentication type is used
user1.SetPassword("");
}
// If a user named 'John' doesn't exist in the database, create this user
SecurityUser user2 = ObjectSpace.FindObject<SecurityUser>(new BinaryOperator("UserName", "John"));
if (user2 == null)
{
user2 = ObjectSpace.CreateObject<SecurityUser>();
user2.UserName = "John";
// Set a password if the standard authentication type is used
user2.SetPassword("");
}
// Add the "Administrators" Role to the user1
user1.Roles.Add(adminRole);
// Add the "Users" Role to the user2
user2.Roles.Add(userRole);
user2.Roles.Add(defaultRole);
// Save the users to the database
user1.Save();
user2.Save();
ObjectSpace.CommitChanges();
SecurityRole anonymousRole = ObjectSpace.FindObject<SecurityRole>(new BinaryOperator("Name", SecurityStrategy.AdministratorRoleName));
if (anonymousRole == null)
{
anonymousRole = ObjectSpace.CreateObject<SecurityRole>();
anonymousRole.Name = SecurityStrategy.AnonymousUserName;
anonymousRole.BeginUpdate();
anonymousRole.Permissions[typeof(SecurityUser)].Grant(SecurityOperations.Read);
anonymousRole.EndUpdate();
anonymousRole.Save();
}
SecurityUser anonymousUser = ObjectSpace.FindObject<SecurityUser>(new BinaryOperator("UserName", SecurityStrategy.AnonymousUserName));
if (anonymousUser == null)
{
anonymousUser = ObjectSpace.CreateObject<SecurityUser>();
anonymousUser.UserName = SecurityStrategy.AnonymousUserName;
anonymousUser.IsActive = true;
anonymousUser.SetPassword("");
anonymousUser.Roles.Add(anonymousRole);
anonymousUser.Save();
}
另外,也可在运行时创建权限控制策略: