Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用Kerberos更改密码协议和.NET Core 3更改Active Directory密码_C#_.net_.net Core_Active Directory_Kerberos - Fatal编程技术网

C# 使用Kerberos更改密码协议和.NET Core 3更改Active Directory密码

C# 使用Kerberos更改密码协议和.NET Core 3更改Active Directory密码,c#,.net,.net-core,active-directory,kerberos,C#,.net,.net Core,Active Directory,Kerberos,可以使用LDAP协议更改AD用户的密码。但是,如果用户必须在下次登录时更改密码(或密码已过期),则除非使用管理员凭据,否则无法更改密码。我能够通过使用WIN32 API解决这个问题。不幸的是,我不能在linux环境中使用WINAPI 根据: 当用户通过按CTRL+ALT+DELETE然后单击更改密码来更改自己的密码时,Windows NT到Windows 2003如果目标是域,则使用NetUserChangePassword机制(方法1)从Windows Vista开始,Kerberos更改密码

可以使用LDAP协议更改AD用户的密码。但是,如果用户必须在下次登录时更改密码(或密码已过期),则除非使用管理员凭据,否则无法更改密码。我能够通过使用WIN32 API解决这个问题。不幸的是,我不能在linux环境中使用WINAPI

根据:

当用户通过按CTRL+ALT+DELETE然后单击更改密码来更改自己的密码时,Windows NT到Windows 2003如果目标是域,则使用NetUserChangePassword机制(方法1)从Windows Vista开始,Kerberos更改密码协议用于域帐户。如果目标是Kerberos领域,则使用Kerberos更改密码协议(方法3)

我寻找可以在.NETCore上运行的Kerberos客户机,发现了

通过阅读和阅读,我编写了以下代码:

using Kerberos.NET;
using Kerberos.NET.Client;
using Kerberos.NET.Credentials;
using Kerberos.NET.Crypto;
using Kerberos.NET.Entities;
using System;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace KerberosDemo
{
    class Program
    {
        static async Task Main(string[] args)
        {
            string activeDirectoryServer = "10.12.34.56:88"; // kdc port
            string domain = "TEST.LOCAL";
            string username = "testuser@" + domain;
            string oldPassword = "123";
            string newPassword = "456";

            using var client = new KerberosClient(activeDirectoryServer);
            var kerbCred = new KerberosPasswordCredential(username, oldPassword, domain);
            await client.Authenticate(kerbCred);
            var serviceTicket = await client.GetServiceTicket("kadmin/changepw");

            var apReq = new KrbApReq
            {
                Ticket = serviceTicket.Ticket,
                Authenticator = KrbEncryptedData.Encrypt(Encoding.UTF8.GetBytes(newPassword).AsMemory(), kerbCred.CreateKey(), KeyUsage.ApReqAuthenticator),
                ProtocolVersionNumber = 1
            };

            var tcp = client.Transports.FirstOrDefault(t => t.Protocol == ProtocolType.Tcp);
            await tcp.SendMessage<KrbApReq, KrbAsRep>(domain, apReq);
        }
    }
}
使用Kerberos.NET;
使用Kerberos.NET.Client;
使用Kerberos.NET.Credentials;
使用Kerberos.NET.Crypto;
使用Kerberos.NET.Entities;
使用制度;
使用System.Linq;
使用System.Net.Sockets;
使用系统文本;
使用System.Threading.Tasks;
命名空间KerberosDemo
{
班级计划
{
静态异步任务主(字符串[]args)
{
字符串activeDirectoryServer=“10.12.34.56:88”;//kdc端口
string domain=“TEST.LOCAL”;
字符串username=“testuser@”+域;
字符串oldPassword=“123”;
字符串newPassword=“456”;
使用var client=newkerberosclient(activeDirectoryServer);
var kerbCred=新KerberosPasswordCredential(用户名、旧密码、域);
等待客户验证(kerbCred);
var serviceTicket=wait client.GetServiceTicket(“kadmin/changepw”);
var apReq=新KrbApReq
{
票证=服务票证。票证,
Authenticator=KrbEncryptedData.Encrypt(Encoding.UTF8.GetBytes(newPassword).AsMemory()、kerbCred.CreateKey()、KeyUsage.ApReqAuthenticator),
ProtocolVersionNumber=1
};
var tcp=client.Transports.FirstOrDefault(t=>t.Protocol==ProtocolType.tcp);
等待tcp.SendMessage(域,apReq);
}
}
}
我在
wait tcp.SendMessage(domain,apReq)上得到了以下异常

未处理的异常。 System.Security.Cryptography.Cryptography异常:ASN1已损坏 数据。在 System.Security.Cryptography.Asn1.AsnReader.ReadTagAndLength(可空
1&
contentsLength、Int32和bytesRead)输入
d:\a\1\s\Kerberos.NET\Asn1\Experimental\AsnReader.cs:at的第305行
Kerberos.NET.Entities.KrbError.CanDecode(ReadOnlyMemory
1编码) d:\a\1\s\Kerberos.NET\Entities\Krb\KrbError.cs: Kerberos.NET.Transport.KerberosTransportBase.Decode[T](只读内存
1
回应)在
d:\a\1\s\Kerberos.NET\Client\Transport\KerberosTransportBase.cs:line
41在
Kerberos.NET.Transport.TcpKerberosTransport.ReadResponse[T](NetworkStream
流,取消令牌取消)在
d:\a\1\s\Kerberos.NET\Client\Transport\TcpKerberosTransport.cs:第69行
在Kerberos.NET.Transport.TcpKerberosTransport.SendMessage[T](字符串
域,ReadOnlyMemory
1编码,取消令牌取消) d:\a\1\s\Kerberos.NET\Client\Transport\TcpKerberosTransport.cs:第58行 在KerberosDemo.Program.Main(字符串[]args)处 程序。(字符串[]args)


谢谢你的帮助。谢谢。

我不妨把这个写进一个答案

如果用户必须在下次登录时更改密码(或密码已过期),则除非使用管理员凭据,否则无法更改密码

如果您使用用户自己的凭据对AD进行身份验证,这可能是一个问题,AD是验证用户凭据的常用方法。如果用户的密码已过期(或特别设置为下次登录时强制更改),则身份验证将失败,您将无法查找用户帐户和更改密码

为了避免这种情况,您可以使用不同的帐户对AD进行身份验证。它不必是管理员帐户。任何域凭据都可以。然后可以查找用户的帐户

由于您必须知道旧密码才能更改密码,因此AD会考虑更改密码所需的所有授权

这与重置密码不同,在重置密码时,您需要对帐户具有“重置密码”权限的帐户

正如您所发现的,您还需要安全地连接到AD,以便新密码不会以明文形式发送


所有这些都记录在。

中,我不妨将其写入答案中

如果用户必须在下次登录时更改密码(或密码已过期),则除非使用管理员凭据,否则无法更改密码

如果您使用用户自己的凭据对AD进行身份验证,这可能是一个问题,AD是验证用户凭据的常用方法。如果用户的密码已过期(或特别设置为下次登录时强制更改),则身份验证将失败,您将无法查找用户帐户和更改密码

为了避免这种情况,您可以使用不同的帐户对AD进行身份验证。它不必是管理员帐户。任何域凭据都可以。然后可以查找用户的帐户

由于您必须知道旧密码才能更改密码,因此AD会考虑更改密码所需的所有授权

这与重置密码不同,在重置密码时,您需要对帐户具有“重置密码”权限的帐户

正如您所发现的,您还需要安全地连接到AD,以便新密码不会以明文形式发送

所有这些