Bagaimana cara pengguna Windows standar mengubah kata sandi mereka dari baris perintah?

18

Pada Windows Server 2008 R2, saya memiliki pengguna lokal standar (non-administrator) (bukan akun Active Directory, meskipun server berada dalam domain) yang memiliki akses ke server hanya melalui PowerShell Remoting. Pengguna tidak dapat masuk melalui RDP.

Saya ingin pengguna ini dapat mengubah kata sandi mereka. Perintah 'pengguna net' memerlukan hak administrator, bahkan jika pengguna mencoba mengubah kata sandi mereka sendiri.

Bagaimana pengguna standar dapat mengubah kata sandi mereka dari baris perintah?

elijahbuck
sumber

Jawaban:

18

Berikut ini beberapa kode PowerShell untuk melakukan apa yang Anda cari dengan akun domain:

param (
    [string]$oldPassword = $( Read-Host "Old password"),
    [string]$newPassword = $( Read-Host "New password")
)

$ADSystemInfo = New-Object -ComObject ADSystemInfo
$type = $ADSystemInfo.GetType()
$user = [ADSI] "LDAP://$($type.InvokeMember('UserName', 'GetProperty', $null, $ADSystemInfo, $null))"
$user.ChangePassword( $oldPassword, $newPassword)

Penyedia ASDI juga mendukung sintaks WinNT://computername/usernameuntuk ChangePassword()metode ini. The ADSystemInfoobjek, bagaimanapun, tidak akan bekerja untuk account mesin-lokal, jadi hanya perkuatan kode di atas dengan WinNT://...sintaks tidak bisa diterapkan.

(Adakah yang ingin menyarankan edit w / kode untuk membedakan antara akun lokal dan domain?)

Pada taktik yang sama sekali berbeda, NetUserChangePasswordAPI lama akan bekerja dengan akun lokal (dan domain, asalkan Anda menentukan nama domain dalam sintaks NetBIOS), juga:

param (
    [string]$oldPassword = $( Read-Host "Old password"),
    [string]$newPassword = $( Read-Host "New password")
)

$MethodDefinition = @'
[DllImport("netapi32.dll", CharSet = CharSet.Unicode)]
public static extern bool NetUserChangePassword(string domainname, string username, string oldPassword, string newPassword);
'@

$NetAPI32 = Add-Type -MemberDefinition $MethodDefinition -Name 'NetAPI32' -Namespace 'Win32' -PassThru

$NetAPI32::NetUserChangePassword('.', $env:username, $oldPassword, $newPassword)

Kode ini mengasumsikan Anda mengubah kata sandi di mesin lokal (".").

Evan Anderson
sumber
1
Anda mengalahkan saya untuk itu, tetapi saya menang untuk konservasi karakter;) Adakah alasan Anda tahu bahwa bagian tambahan yang Anda gunakan diperlukan? Atau hanya untuk menjadi lebih formal dan pantas?
charleswj81
1
Anda pasti mendapatkan penghargaan kode golf. Saya hanya formal dan layak ... Sebenarnya, ini terutama membuat skrip sedikit lebih bermanfaat bagi orang lain yang mungkin tipe cut-and-paste.
Evan Anderson
1
@ charleswj81 - Jawaban Evan jauh lebih lengkap. Ini adalah PS1skrip mandiri yang dapat dipanggil dengan atau tanpa parameter. Ini jauh lebih mudah dibaca juga. Kode adalah tentang manusia yang memahami apa yang ditulis orang lain, bukan komputer. Tidak ada solusi yang lebih cepat dari yang lain.
Mark Henderson
1
Ini terlihat menjanjikan, tetapi saya harus mengklarifikasi bahwa akun tersebut sesuai dengan sistem. Saya mencoba yang berikut: ([ADSI]'WinNT://localhost/USERNAME').ChangePassword("OLDPASS", "NEWPASS") Tapi itu mengembalikan 'Kata sandi tidak memenuhi persyaratan kebijakan kata sandi ...'. Kata sandi baru memang memenuhi persyaratan itu.
elijahbuck
1
Sebenarnya, setelah menambahkan pengguna ke 'Remote Desktop Users' dan mencoba mengubah kata sandi dengan cara itu, saya mendapatkan kesalahan yang sama. Saya percaya bahwa cara yang benar untuk mengubah akun lokal adalah: ([ADSI]'WinNT://localhost/USERNAME').ChangePassword("OLDPASS", "NEWPASS")
elijahbuck
9

Ini sebenarnya cukup sederhana di PowerShell:

([ADSI]'LDAP://CN=User,CN=Users,DC=domain').ChangePassword('currentpassword','newpassword')
charleswj81
sumber
3

Saya mencoba kedua jawaban di atas tidak berhasil, untuk mengubah kata sandi admin lokal yang tidak bergabung dengan domain. Menggali komentar menghasilkan apa yang saya butuhkan.

Untuk bagian kedua dari jawaban yang saat ini diterima, Anda ingin memperbarui tanda tangan untuk digunakan longalih-alih boolnilai balik, dan ini dapat dipecahkan di atas pada kode kesalahan sistem docs . Jadi, Anda berakhir dengan:

param (
    [string]$oldPassword = $( Read-Host "Old password"),
    [string]$newPassword = $( Read-Host "New password")
)

$MethodDefinition = @'
[DllImport("netapi32.dll", CharSet = CharSet.Unicode)]
public static extern **long** NetUserChangePassword(string domainname, string username, string oldPassword, string newPassword);
'@

$NetAPI32 = Add-Type -MemberDefinition $MethodDefinition -Name 'NetAPI32' -Namespace 'Win32' -PassThru

$NetAPI32::NetUserChangePassword('.', $env:username, $oldPassword, $newPassword)

Namun, itu tidak berhasil untuk saya. Kode kesalahan berganti-ganti antara 86 dan 2221, tergantung pada bagaimana saya mengatur parameter. Akan menyerah dan menggali lebih dalam komentar, dan akhirnya menemukan keberhasilan dalam melakukan:

([ADSI]'WinNT://./USERNAME').ChangePassword("OLDPASS‌​", "NEWPASS")

Benar-benar konyol bahwa PERUBAHAN kata sandi admin lokal sangat rumit di Powershell. Jika Anda menyimpan securestrings sama sekali di sistem Anda, maka memperbarui kata sandi harus dilakukan dengan memasok kata sandi lama, atau berisiko kehilangan kemampuan untuk mendekripsi string aman dengan benar!

Gnalck
sumber