Làm thế nào một người dùng Windows tiêu chuẩn có thể thay đổi mật khẩu của họ từ dòng lệnh?


18

Trên Windows Server 2008 R2, tôi có một người dùng cục bộ tiêu chuẩn (không phải quản trị viên) (không phải tài khoản Active Directory, mặc dù máy chủ nằm trong một miền) chỉ có quyền truy cập vào máy chủ thông qua PowerShell Remote. Người dùng không thể đăng nhập qua RDP.

Tôi muốn người dùng này có thể thay đổi mật khẩu của họ. Lệnh 'người dùng mạng' yêu cầu quyền quản trị viên, ngay cả khi người dùng đang cố gắng thay đổi mật khẩu của riêng họ.

Làm thế nào một người dùng tiêu chuẩn có thể thay đổi mật khẩu của họ từ dòng lệnh?

Câu trả lời:


18

Đây là một số mã PowerShell để thực hiện những gì bạn đang tìm kiếm với tài khoản miền:

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)

Nhà cung cấp ASDI cũng hỗ trợ cú pháp WinNT://computername/usernamecho ChangePassword()phương thức. Các ADSystemInfođối tượng, tuy nhiên, sẽ không làm việc cho các tài khoản máy địa phương, vì vậy chỉ cần trang bị thêm các mã trên với WinNT://...cú pháp là không khả thi.

(Bất kỳ ai cũng muốn đề xuất chỉnh sửa w / code để phân biệt giữa tài khoản cục bộ và tài khoản miền?)

Trên một chiến thuật hoàn toàn khác, NetUserChangePasswordAPI cũ cũng sẽ hoạt động với các tài khoản cục bộ (và tên miền, miễn là bạn chỉ định tên miền trong cú pháp NetBIOS):

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)

Mã này giả sử bạn đang thay đổi mật khẩu trên máy cục bộ (".").


1
Bạn đánh bại tôi với nó, nhưng tôi giành chiến thắng để bảo tồn các nhân vật;) Bất kỳ lý do nào bạn biết về việc các phần bổ sung bạn sử dụng là cần thiết? Hay chỉ để trang trọng và đúng đắn hơn?
charleswj81

1
Bạn chắc chắn nhận được giải thưởng golf mã. Tôi chỉ là người chính thức và đúng đắn ... Trên thực tế, nó chủ yếu làm cho kịch bản trở nên hữu dụng hơn một chút đối với những người khác có thể là kiểu cắt và dán.
Evan Anderson

1
@ charleswj81 - Câu trả lời của Evan hoàn thiện hơn. Đó là một PS1tập lệnh độc lập có thể được gọi có hoặc không có tham số. Nó cũng dễ đọc hơn nhiều. Mã là tất cả về con người hiểu những gì người khác đã viết, không phải máy tính. Không giải pháp nào sẽ nhanh hơn giải pháp kia.
Mark Henderson

1
Điều này có vẻ đầy hứa hẹn, nhưng tôi nên làm rõ rằng tài khoản là cục bộ của hệ thống. Tôi đã thử như sau: ([ADSI]'WinNT://localhost/USERNAME').ChangePassword("OLDPASS", "NEWPASS") Nhưng điều đó đã trả về 'Mật khẩu không đáp ứng các yêu cầu chính sách mật khẩu ...'. Mật khẩu mới đáp ứng những yêu cầu đó.
elijahbuck

1
Trên thực tế, sau khi thêm người dùng vào 'Người dùng máy tính từ xa' và thử thay đổi mật khẩu theo cách đó, tôi cũng gặp lỗi tương tự. Tôi tin rằng cách chính xác để thay đổi tài khoản địa phương là: ([ADSI]'WinNT://localhost/USERNAME').ChangePassword("OLDPASS", "NEWPASS")
elijahbuck

9

Điều này thực sự khá đơn giản trong PowerShell:

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

3

Tôi đã thử cả hai câu trả lời ở trên nhưng không có kết quả, vì đã thay đổi mật khẩu của quản trị viên cục bộ không tham gia tên miền. Đào qua các ý kiến ​​mang lại những gì tôi cần mặc dù.

Đối với phần thứ hai của câu trả lời hiện được chấp nhận, bạn muốn cập nhật chữ ký để sử dụng longthay vì boolgiá trị trả về và chúng có thể được khắc phục sự cố tại các tài liệu mã lỗi hệ thống . Vì vậy, bạn kết thúc với:

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)

Tuy nhiên, điều đó không làm việc cho tôi. Các mã lỗi xen kẽ giữa 86 và 2221, tùy thuộc vào cách tôi thiết lập các tham số. Đã từ bỏ và đào sâu hơn vào các bình luận, và cuối cùng đã tìm thấy thành công trong việc thực hiện:

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

Hoàn toàn vô lý khi THAY ĐỔI một mật khẩu quản trị viên cục bộ quá phức tạp trong Powershell. Nếu bạn lưu trữ tất cả các chuỗi bảo mật trên hệ thống của mình, thì việc cập nhật mật khẩu phải được thực hiện bằng cách cung cấp mật khẩu cũ hoặc có nguy cơ mất khả năng giải mã chính xác các chuỗi bảo mật đó!

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.