【问题标题】:C# clr udf for Active Directory group membershipC# clr udf 用于 Active Directory 组成员身份
【发布时间】:2017-07-20 23:30:03
【问题描述】:

我的问题如下:我需要一个 clr udf(在 C# 中)来使用给定的 ad-usr 查询广告组成员身份

using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
using System.DirectoryServices.AccountManagement;

public partial class UserDefinedFunctions
{
    [Microsoft.SqlServer.Server.SqlFunction]
    public static SqlInt32 check_user_is_part_of_ad_grp(SqlString ad_usr, SqlString ad_grp)
    {
        bool bMemberOf = false;

        // set up domain context
        PrincipalContext ctx = new PrincipalContext(ContextType.Domain);

        // find the group in question
        GroupPrincipal group = GroupPrincipal.FindByIdentity(ctx, ad_grp.ToString());
        UserPrincipal usr = UserPrincipal.FindByIdentity(ctx, ad_usr.ToString());

        if (group != null && usr != null)
        {
            bMemberOf = usr.IsMemberOf(group);
        }

        // Put your code here
        return new SqlInt32 (bMemberOf ? 1 : 0);
    }
}

如果我将 CLR 发布到我的 SQL Server 2008 (.net 3.5),那么我按如下方式运行 udf:

select dbo.check_user_is_part_of_ad_grp('user', 'group')

我得到一个错误:

消息 6522,第 16 级,状态 1,第 1 行
在执行用户定义的例程或聚合“check_user_is_part_of_ad_grp”期间发生 .NET Framework 错误:
System.Security.SecurityException:请求“System.DirectoryServices.DirectoryServicesPermission,System.DirectoryServices,Version=2.0.0.0,Culture=neutral,PublicKeyToken=b03f5f7f11d50a3a”类型的权限失败。
System.Security.SecurityException:
在 UserDefinedFunctions.check_user_is_part_of_ad_grp(SqlString ad_usr, SqlString ad_grp)

我将项目的目标框架设置为3.5,权限级别设置为EXTERNAL_ACCESS。还有项目参考(System.DirectoryServicesSystem.DirectoryServices.AccountManamgementSystem.DirectoryServices.Protocols)到EXTERNAL

感谢您的帮助

【问题讨论】:

    标签: c# sql-server-2008 active-directory sqlclr udf


    【解决方案1】:

    很可能所有这些程序集都需要设置为 UNSAFE,尤其是您导入的三个 System.DirectoryServices* .NET Framework 库。此外,由于您正在导入unsupported .NET Framework libraries,因此您需要将数据库设置为TRUSTWORTHY ON 才能使它们正常工作。将数据库设置为TRUSTWORTHY ON 通常是您要避免的,因为它存在安全风险,但在这种情况下,我认为无法避免。

    也就是说,我不确定您是否需要自己在 SQLCLR 中创建此函数。如果您只是想知道某个登录名(显然仅限于 Windows 登录名)是否属于特定的 Active Directory 组,则有一个内置函数应该为您执行此操作。 IS_MEMBER 函数将指示 current 登录是否是指定 Windows 组(指定为 Domain\Group)的成员。此功能与您正在创建的功能的不同之处在于它仅适用于当前登录;您不能将任何任意登录名传递给它。但是,它也不需要作为 this SQLCLR 解决方案一部分的任何额外工作和安全风险。所以,需要考虑的事情:-)。

    OP 对此答案的评论:

    实际上,如果它是特定组的成员,我需要检查任意登录。我什至尝试将存储过程和“OPENQUERY”与链接服务器一起使用到 ADSI,但这只能用作动态 SQL,因为我需要注入组和用户。

    在这种情况下,只需将 Dynamic SQL 设置为两层,而不是通常的一层。大致如下:

    DECLARE @SQL NVARCHAR(MAX);
    SET @SQL = N'
      SELECT *
      FROM   OPENQUERY([LinkedServer], N''
                 SELECT *
                 FROM   someResource
                 WHERE  GroupName=N''''' + @Group + N'''''
                 AND    ObjectName=N''''' + @Login + N''''';
                       '');
    ';
    
    PRINT @SQL; -- DEBUG
    EXEC (@SQL);
    

    在这种方法中,执行OPENQUERY 的查询是动态SQL,但给OPENQUERY 执行的查询是字符串文字。

    【讨论】:

    • 实际上我需要检查任意登录名,如果它是特定组的成员。我什至尝试使用存储过程和带有链接服务器到 ADSI 的 openquery 但这只能用作动态 sql,因为我需要注入组和用户,因为我们有一个包含许多组和用户的巨大广告。
    • 链接服务器到 ADSI 是否工作?您可以通过创建动态 SQL 以包含整个 OPENQUERY 调用然后执行它来绕过 OPENQUERY 的动态 SQL 限制。
    • 我没明白.. 你的意思是我可以绕过 dyn-sql 限制?你有例子吗?
    • 如果我这样做,我将收到错误消息 443,在函数中无效使用副作用运算符“执行字符串”
    • @rudash04 正确,这不能在函数中完成。它需要存放在存储过程中。如果你有一个列表,那么你需要使用游标遍历列表并为每个值调用存储过程。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-12
    相关资源
    最近更新 更多