假设我们有一个名为SalesSummary的报告,适用于大型部门。该部门每个产品都有许多小型团队。人们应该能够看到有关他们自己产品的信息,而不是其他团队的产品。我们每个团队都有一个域组。
为每个团队复制SalesSummary报告并设置权限不是最佳选择,因为我们有很多产品。我想在RS上使用类似下面的代码,但它不起作用。显然,RS上默认禁用System.Security.Principal.WindowsPrincipal。
Public Function isPermitted() As Boolean
Dim Principal As New System.Security.Principal.WindowsPrincipal(System.Security.Principal.WindowsIdentity.GetCurrent())
If (Principal.IsInRole("group_prod")) Then
Return true
Else
Return false
End If
End Function
我还以为我可以将用户ID从RS发送到SQL服务器,在我的SP中我可以使用类似下面的代码来查询活动目录。由于安全限制,这也不起作用。
SELECT
*
FROM OPENQUERY(ADSI,'SELECT cn, ADsPath FROM ''LDAP://DC=Fabricam,DC=com'' WHERE objectCategory=''group''')
有没有更简单的方法来实现这一目标?
感谢您的帮助!
答案 0 :(得分:3)
您建议的第一个选项(使用嵌入式代码识别正在执行的用户)将不可靠。 SSRS代码不一定以访问报告的用户身份执行,并且可能无法访问该用户凭据,例如在运行订阅时。
您的第二种方法可行,但需要SQL服务器服务帐户的相应权限才能查询Active Directory。
另一种方法是在SQL表中维护组成员身份或用户权限的副本。该表可以手动更新或通过自动化过程更新。然后,您可以轻松地将其合并到可用参数和核心数据查询中。
答案 1 :(得分:1)
所以我最终得到了这段代码:
PrincipalContext domain = new PrincipalContext(ContextType.Domain, "AD");
UserPrincipal user = UserPrincipal.FindByIdentity(domain, identityName);
//// if found - grab its groups
if (user != null)
{
PrincipalSearchResult<Principal> _groups = null;
int tries = 0;
//We have this while because GetGroups sometimes fails! Specially if you don't
// mention the domain in PrincipalContext
while (true)
{
try
{
_groups = user.GetGroups();
break;
}
catch (Exception ex)
{
logger.Debug("get groups failed", ex);
if (tries > 5) throw;
tries++;
}
}
// iterate over all groups, just gets groups related to this app
foreach (Principal p in _groups)
{
// make sure to add only group principals
if (p is GroupPrincipal)
{
if (p.Name.StartsWith(GROUP_IDENTIFIER))
{
this.groups.Add((GroupPrincipal)p);
this.groupNames.Add(p.Name);
}
}
}
}
现在,您有一个相关组列表,您可以查看列表以授权用户!