简体   繁体   English

C#clr udf用于Active Directory组成员身份

[英]C# clr udf for Active Directory group membership

My problem is as follows: I need a clr udf (in C#) to query with a given ad-usr the ad-group membership 我的问题如下:我需要一个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);
    }
}

If I publish the CLR to my SQL Server 2008 (.net 3.5), then I run the udf as follows: 如果我将CLR发布到我的SQL Server 2008(.net 3.5),那么我按如下方式运行udf:

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

And I get an error: 我收到一个错误:

Msg 6522, Level 16, State 1, Line 1 Msg 6522,Level 16,State 1,Line 1
A .NET Framework error occurred during execution of user-defined routine or aggregate "check_user_is_part_of_ad_grp": 执行用户定义的例程或聚合“check_user_is_part_of_ad_grp”期间发生.NET Framework错误:
System.Security.SecurityException: Request for the permission of type 'System.DirectoryServices.DirectoryServicesPermission, System.DirectoryServices, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' failed. System.Security.SecurityException:对类型'System.DirectoryServices.DirectoryServicesPermission,System.DirectoryServices,Version = 2.0.0.0,Culture = neutral,PublicKeyToken = b03f5f7f11d50a3a'的权限的请求失败。
System.Security.SecurityException: System.Security.SecurityException:
at UserDefinedFunctions.check_user_is_part_of_ad_grp(SqlString ad_usr, SqlString ad_grp) 在UserDefinedFunctions.check_user_is_part_of_ad_grp(SqlString ad_usr,SqlString ad_grp)

I set the target framework of my project to 3.5 and the permission level to EXTERNAL_ACCESS . 我将项目的目标框架设置为3.5,将权限级别设置为EXTERNAL_ACCESS Also the project references ( System.DirectoryServices , System.DirectoryServices.AccountManamgement , System.DirectoryServices.Protocols ) to EXTERNAL 项目引用( System.DirectoryServicesSystem.DirectoryServices.AccountManamgementSystem.DirectoryServices.Protocols )到EXTERNAL

I appreciate any help 我感谢任何帮助

Most likely all of those Assemblies will need to be set to UNSAFE , especially the three System.DirectoryServices* .NET Framework libraries that you imported. 很可能所有这些程序集都需要设置为UNSAFE ,尤其是您导入的三个System.DirectoryServices * .NET Framework库。 Also, since you are importing unsupported .NET Framework libraries , you will need to set the database to TRUSTWORTHY ON in order to get them to work. 此外,由于您要导入不受支持的.NET Framework库 ,因此您需要将数据库设置为TRUSTWORTHY ON才能使它们正常工作。 Setting a Database to TRUSTWORTHY ON is typically something you want to avoid as it is a security risk, but in this case I do not believe that it can be avoided. 将数据库设置为TRUSTWORTHY ON通常是您要避免的,因为它存在安全风险,但在这种情况下,我不相信它可以避免。

That said, I am not sure that you even need to create this function yourself in SQLCLR. 也就是说,我不确定您是否需要在SQLCLR中自己创建此功能。 If you are just wanting to know if a Login (Windows Logins only, obviously) belongs to a particular Active Directory group, there is a built-in function that should do that for you. 如果你只是想知道,如果一个登录(Windows登录唯一的,很明显)属于特定的Active Directory组,有一个内置的功能应该为你做的。 The IS_MEMBER function will indicate if the current Login is a member of the specified Windows group (specified as Domain\\Group ). IS_MEMBER函数将指示当前 Login是否是指定Windows组(指定为Domain\\Group )的成员。 The difference in how this function works as opposed to the one that you are creating is that it only works for the current Login; 与您正在创建的函数相比,此函数的工作方式不同之处在于它仅适用于当前的Login; you cannot pass any arbitrary Login into it. 你无法通过任意登录。 BUT, it also doesn't require any of the extra effort and security risks that are a part of this SQLCLR solution. 但是,这也并不需要任何的是这个 SQLCLR解决方案的一部分额外的努力和安全风险。 So, something to consider :-). 所以,需要考虑的事情:-)。

Comment from OP on this answer: OP对此答案的评论:

Actually, I need to check an arbitrary Login if it's member of a particular group. 实际上,如果它是特定组的成员,我需要检查任意登录。 I even tried to use a stored proc and `OPENQUERY' with a linked server to ADSI, but this only works as Dynamic SQL since I need to inject group and user. 我甚至尝试将存储过程和“OPENQUERY”与链接服务器一起用于ADSI,但这只能用作动态SQL,因为我需要注入组和用户。

In that case, just make the Dynamic SQL two layers deep instead of the usual one layer. 在这种情况下,只需将动态SQL两层深层而不是通常的一层。 Something along the lines of: 有点像:

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);

In this approach, the query executing OPENQUERY is Dynamic SQL, but the query given to OPENQUERY to execute is a string literal. 在此方法中,执行OPENQUERY的查询是动态SQL,但是给OPENQUERY执行的查询是字符串文字。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM