使用协议转换 - 防御提示
2009-02-09 13:52:49 来源:WEB开发网内核对象和 ACL
需要牢记的另一件关于 Windows 内核对象的事情是:每一个内核对象都使用访问控制列表 (ACL)(包括您要发送回的令牌)来确保安全性。从技术角度看,由于您要将句柄复制回给调用方,只要调用方能够使用这个特定句柄,ACL 就应当无关紧要。但是,调整令牌中的 ACL 以确保调用方的安全主体有使用令牌的权限不失为明智之举,特别是,考虑到调用方可能要使用 .NET 包装(如 WindowsIdentity)来操作令牌句柄。最终结果可能是拒绝调用方拥有使用您提供给他的令牌的权限。
遗憾的是,.NET Framework 还没有提供一个允许您直接操作令牌的类。WindowsIdentity 是目前框架中最接近 Token 类的类。不过,我借此机会将 System.Security.AccessControl 中的类进行了扩展以支持在令牌中读取和写入 ACL。我记得以前曾经对此进行过介绍,不过我仍然要对开发 AccessControl 命名空间的 Windows 团队成员表示感谢。扩展他们的 NativeObjectSecurity 来支持令牌出奇的容易方便。图 2 显示了我是如何实现 TokenSecurity 的。(本专栏的下载内容中提供了完整的代码。)乍一看可能代码很多,但如果仔细查看,您会发现所有代码要做的都是为令牌自定义 ACL。其中最让人感兴趣的代码是 TokenRights 枚举;而所有其他代码都是程式化的内容。
Figure2扩展 AccessControl 以支持令牌安全
public enum TokenRights : int {
AssignPrimary = 0x0001,
Duplicate = 0x0002,
Impersonate = 0x0004,
Query = 0x0008,
QuerySource = 0x0010,
AdjustPrivileges = 0x0020,
AdjustGroups = 0x0040,
AdjustDefault = 0x0080,
AdjustSessionId = 0x0100,
Read = 0x00020008,
Write = 0x000200E0,
Execute = 0x00020000,
All = 0x000F00FF, // TOKEN_ALL_ACCESS_P
AllPlusSessionId= 0x000F01FF, // TOKEN_ALL_ACCESS
MaximumAllowed = 0x02000000,
AccessSystemSecurity = 0x01000000,
}
public class TokenAccessRule : AccessRule {
public TokenAccessRule(IdentityReference identity,
TokenRights tokenRights, AccessControlType aceType)
: base(identity, (int)tokenRights,
false, InheritanceFlags.None,
PropagationFlags.None, aceType) {
}
public TokenRights TokenRights {
get { return (TokenRights)base.AccessMask; }
}
}
public class TokenAuditRule : AuditRule {
public TokenAuditRule(IdentityReference identity,
TokenRights tokenRights, AuditFlags auditFlags)
: base(identity, (int)tokenRights,
false, InheritanceFlags.None,
PropagationFlags.None, auditFlags) {
}
public TokenRights TokenRights {
get { return (TokenRights)base.AccessMask; }
}
}
public class TokenSecurity : NativeObjectSecurity {
public TokenSecurity()
: base(false, ResourceType.KernelObject) {
}
public TokenSecurity(SafeTokenHandle token)
: this(token,
AccessControlSections.Owner |
AccessControlSections.Group |
AccessControlSections.Access) {
}
public TokenSecurity(SafeTokenHandle token,
AccessControlSections includeSections)
: base(false, ResourceType.KernelObject,
token, includeSections) {
}
public override Type AccessRightType {
get { return typeof(TokenRights); }
}
public override Type AccessRuleType {
get { return typeof(TokenAccessRule); }
}
public override Type AuditRuleType {
get { return typeof(TokenAuditRule); }
}
public override AccessRule AccessRuleFactory(
IdentityReference identity, int accessMask,
bool isInherited, InheritanceFlags inheritanceFlags,
PropagationFlags propagationFlags,
AccessControlType aceType) {
return new TokenAccessRule(identity,
(TokenRights)accessMask, aceType);
}
public override AuditRule AuditRuleFactory(
IdentityReference identity, int accessMask,
bool isInherited, InheritanceFlags inheritanceFlags,
PropagationFlags propagationFlags, AuditFlags auditFlags) {
return new TokenAuditRule(identity,
(TokenRights)accessMask, auditFlags);
}
public void AddAccessRule(TokenAccessRule rule) {
base.AddAccessRule(rule);
}
public void AddAuditRule(TokenAuditRule rule) {
base.AddAuditRule(rule);
}
public void Persist(SafeTokenHandle token,
AccessControlSections includeSections) {
base.Persist(token, includeSections);
}
}
登录服务的实现如图 3 所示。您可能需要注意的首要问题是 System.EnterpriseServices 属性,这些属性为 COM+ 目录中的宿主准备了 LogonService 程序集和类。您应当特别关注需要对调用方进行验证以及需要让调用方以特定角色调用登录服务的安全属性。(我使用了称为 ProtocolTransitionUsers 的角色,并确保在部署登录服务并在 COM+ 目录中对服务进行配置时,运行我的网关所使用的安全主体是此角色的一个成员。)
更多精彩
赞助商链接