简体   繁体   English

使用服务帐户的Active Directory身份验证

[英]Active Directory Authentication using services account

I'm working on Web Services which authenticates users against Active Directory . 我正在研究Web Services ,该Web Services可根据Active Directory对用户进行身份验证。 My current solution is working, however, I'm trying to take a different approach. 我当前的解决方案正在工作,但是,我正在尝试采用另一种方法。

I have an Active Directory (production) which is sitting behind the firewall. 我的Active Directory (生产版本)位于防火墙后面。 I also installed an Active Directory in DMZ . 我还在DMZ安装了Active Directory There's a one way relationship between them. 它们之间存在一种单向关系。 DMZ trusts production and production doesn't care about DMZ . DMZ相信生产和生产无关DMZ

What I'm trying to accomplish is Authenticate everyone through DMZ Active Directory . 我要完成的工作是通过DMZ Active Directory每个人进行身份验证。 Currently, based on the username I know which AD server to authenticate against. 目前,基于用户名,我知道要针对哪个AD服务器进行身份验证。

For example, my production Active Directory (let say domain domain.local ) and my DMZ Active directory (let say domain domain.public ). 例如,我的生产Active Directory(比如说domain domain.local )和DMZ Active目录(比如说domain domain.public )。 Before I do authentication against any AD server, I check if the username provided exists in one of the server. 在对任何AD服务器进行身份验证之前,我会检查提供的用户名是否存在于其中一台服务器中。 Then, I check if the user is active and only then I do authentication. 然后,我检查用户是否处于活动状态,然后才进行身份验证。 (I'm having issues in the first function. It never reaches to the second or third functions). (我在第一个功能中遇到了问题。它从来没有达到第二个或第三个功能)。

UPDATE: ADDED EVERYTHING: 更新:添加了所有内容:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using System.DirectoryServices;
using System.Security.Principal;
using System.DirectoryServices.AccountManagement;

namespace ActiveDirectory
{
// NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "Service1" in both code and config file together.
public class Service1 : IService1
{
    #region Does User Exist in AD

    public string local = string.Empty;
    public string ldappath = string.Empty;
    public string userNameToUse = string.Empty;
    public string domain = string.Empty;

    public bool DoesUserExist(string userName)
    {
        string _userName = userName;

        bool exist = true;

        using (var domainContext = new PrincipalContext(ContextType.Domain, domain))
        {
            using (var foundUser = UserPrincipal.FindByIdentity(domainContext, IdentityType.SamAccountName, userNameToUse))
            {
                if (foundUser == null)
                {
                    exist = false;
                }
                else
                {
                    return exist;
                }
            }
        }
        return exist;
    }

    #endregion

    #region Check if User Active
    public bool isActive (string userName)
    {
        string _userNameToBeSearched = userNameToUse;
        string _username = string.Empty;
        string _pwd = string.Empty;

        if (local == "YES")
        {
             _username = "xx";
             _pwd = "xx";
            ldappath = "LDAP://xxx/DC=xx, DC=local";
        }
        else
        {
             _username = "xx";
             _pwd = "xx";
             ldappath = "LDAP://xxx/DC=xx, DC=public";
        }

        bool isActive = true;

        try
        {
            DirectoryEntry entry = new DirectoryEntry(ldappath, _username, _pwd);
            DirectorySearcher search = new DirectorySearcher(entry);
            entry.AuthenticationType = AuthenticationTypes.Secure;
            search.SearchRoot = entry;
            search.Filter = "(SAMAccountName=" + _userNameToBeSearched + ")";

            SearchResult results = search.FindOne();

            if (results.ToString() != "")
            {
                int flags = Convert.ToInt32(results.Properties["userAccountControl"][0].ToString());

                //CHECK IF THE ACCOUNT IS DISABLED
                if (flags == 66050)
                {
                    isActive = false;
                }
            }
        }
        catch (DirectoryServicesCOMException ex)
        {
            ex.ToString();
        }
        return isActive;
    }

    #endregion

    #region Is user authenticated
    public string isAuthenticated (string userName, string pwd)
    {
        string _userName, _pwd, message;
        _userName = userName;
        _pwd = pwd;

        char[] splitchar = { '@' };

        string[] strSplit = _userName.Split(splitchar);

        string z = strSplit[0];

        if (strSplit.Length == 2)
        {
            domain = "x.public";
            userNameToUse = z.ToString();
            local = "NO";
        }
        else
        {
            domain = "x.local";
            userNameToUse = z.ToString();
            local = "YES";
        }

        if (DoesUserExist (userNameToUse) == true)
        {
            if (isActive(userNameToUse) == true)
            {
                try
                {
                    DirectoryEntry entry = new DirectoryEntry(ldappath, userNameToUse, _pwd);
                    object nativeObject = entry.NativeObject;
                    var GUIDID = "";

                    using (var domainContext = new PrincipalContext(ContextType.Domain, domain))
                    {
                        using (var user = UserPrincipal.FindByIdentity(domainContext, IdentityType.SamAccountName, userNameToUse))
                        {
                            if (user != null)
                            {
                                GUIDID = user.Guid.ToString();
                            }
                        }
                        message = "Successfully authenticated:" + GUIDID;
                    }
                }
                catch (DirectoryServicesCOMException)
                {
                    message = "Invalid password.";
                }
            }
            else
            {
                message = "Account is disabled";
            }
        }
        else
        {
            message = "There's an issue with your account.";
        }
        return message;      
    }

    #endregion
}
}

If username exists in DMZ AD it will return true else it will return false. 如果DMZ AD中存在用户名,它将返回true,否则将返回false。 However, there're going to be users who will only exists in production AD, but will not have any entry in DMZ. 但是,将会有一些用户仅存在于生产AD中,而在DMZ中没有任何条目。 Since, I built ONE WAY trust I should be able to do this: 由于建立了单向信任,因此我应该能够做到这一点:

username@domain.local for production and username@domain.public However, even though I specify fully username if entry doesn't exists in DMZ AD it will return null although it exists in production AD. username@domain.local生产和username@domain.public然而,即使我完全指定用户名称,条目没有在DMZ AD存在,它将返回null虽然它在生产AD存在。

Any suggestion, on how I can authenticate everybody through DMZ AD using webservices account which has full permission to production AD? 关于如何使用拥有生产AD完全权限的webservices帐户通过DMZ AD验证每个人的任何建议?

Note if needed I can provide the rest of the code...* 请注意,如果需要,我可以提供其余代码... *

Thanks 谢谢

What is the value of domain in the PrincipalContext? PrincipalContext中domain的值是什么? If you aren't already, you'll need to use the proper domain for the user you're looking up to user your current code. 如果尚未注册,则需要为要查找的用户使用正确的域以使用当前代码。 PrincipalContext does not support searches across domains in your forest. PrincipalContext不支持在林中跨域搜索。

Here is an example of using a DirectorySearcher to do it. 这是使用DirectorySearcher进行操作的示例

The code has several issues, I only talk about major ones. 该代码有几个问题,我只谈论主要的问题。

  1. In method DoesUserExist you use service account (no credential is passed to PrincipalContext ) to query both domains. 在方法DoesUserExist您使用服务帐户(没有凭据传递给PrincipalContext )来查询两个域。 But in method isActive you have different credentials for different domains. 但是在方法isActive您对不同的域具有不同的凭据。 So we have 3 credentials for 2 domains... 因此,我们拥有2个域的3个凭据...

    At least use a consistent way for both methods. 至少对于两种方法都使用一致的方式。

  2. For 1-way trust(eg A trusts B), accounts in B should be able to access both domain A and B. 对于单向信任(例如,A信任B),B中的帐户应能够访问域A和B。

    May be you can simply use an account in trusted domain as service account. 可能您可以简单地将受信任域中的帐户用作服务帐户。 And then use service account (null to username and password) to perform all AD access. 然后使用服务帐户(用户名和密码为空)执行所有AD访问。 So you don't even need to put password in your code. 因此,您甚至无需在代码中输入密码。

  3. In isActive , where does the "66050" come from? isActive ,“ 66050”来自哪里?
    66060 is 10202 in hex, which means (1)user, (2)disabled and (3)don't expire password. 66060是十六进制的10202,表示(1)用户,(2)禁用和(3)不过期密码。

    To check if an account is enabled, check only the ACCOUNTDISABLE bit (0x0002). 要检查是否启用了帐户,请仅检查ACCOUNTDISABLE位(0x0002)。 It should be 0 for enabled. 启用时应为0。

  4. You already get the UserPrincipal in DoesUserExist . 您已经在DoesUserExist中获得了DoesUserExist Can simply check enabled by looking at UserPrincipal.Enabled . 只需查看UserPrincipal.Enabled可以检查启用UserPrincipal.Enabled

I need to do code review in my daily work. 我需要在日常工作中进行代码审查。 Now I'm doing it also on Stack Overflow... :) 现在,我也在堆栈溢出... :)

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

相关问题 使用Active Directory的Silverlight身份验证 - Silverlight authentication using Active Directory 与自定义滚动身份验证和访问方案相比,使用 Active Directory 轻量级目录服务(又名 ADAM)有哪些优势? - What are the advantages of using Active Directory Lightweight Directory Services (a.k.a. ADAM) over a custom-rolled authentication & access scheme? 无法使用 Azure Active Directory 连接到连接服务身份验证 - Can't connect to Connected Services Authentication with Azure Active Directory 使用c#中的vpn进行活动目录身份验证 - Active directory authentication using vpn in c# 在Intranet中使用Active Directory进行登录身份验证...可能吗? - Login Authentication using Active Directory in the Intranet…Possible? 使用C#对Active Directory进行身份验证 - Authentication against Active Directory using C# 使用活动目录的MVC 5身份验证,没有单一登录 - MVC 5 authentication using active directory with no single sign on 使用 Angular 8 和 Azure Active Directory 进行身份验证 - Authentication using Angular 8 with Azure Active Directory 使用 Azure Active Directory 的 Azure Function 身份验证 - Azure Function authentication using Azure Active Directory 查询活动目录的帐号 - Account to query the active directory
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM