C# 使用Kerberos更改密码协议和.NET Core 3更改Active Directory密码
可以使用LDAP协议更改AD用户的密码。但是,如果用户必须在下次登录时更改密码(或密码已过期),则除非使用管理员凭据,否则无法更改密码。我能够通过使用WIN32 API解决这个问题。不幸的是,我不能在linux环境中使用WINAPI 根据: 当用户通过按CTRL+ALT+DELETE然后单击更改密码来更改自己的密码时,Windows NT到Windows 2003如果目标是域,则使用NetUserChangePassword机制(方法1)从Windows Vista开始,Kerberos更改密码协议用于域帐户。如果目标是Kerberos领域,则使用Kerberos更改密码协议(方法3) 我寻找可以在.NETCore上运行的Kerberos客户机,发现了 通过阅读和阅读,我编写了以下代码: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更改密码
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,以便新密码不会以明文形式发送
所有这些