Share via


嗨,Scripting Guy!

Hey,Scripting Guy!

歡迎使用全新的 TechNet 專欄,Microsoft Scripting Guys 會在此為您解答有關系統管理指令碼的常見問題。您有關於系統管理指令碼方面的問題嗎?請將電子郵件傳送到 scripter@microsoft.com。我們無法保證能夠逐一回答每個問題,不過我們會盡力而為。

今天的問題:如何防止本機使用者變更他們的密碼?


如何防止本機使用者變更他們的密碼?

嗨,Scripting Guy!請問我要如何設定本機使用者帳戶,才能讓他們無法變更自己的密碼?

-- DC

DC,您好。這其中的奧秒就在於神奇的 userFlags 屬性。讓我先示範如何設定使用者帳戶,讓使用者無法變更自己的密碼;然後再補充說明一些可以用 userFlags 屬性 (Attribute) 管理的本機使用者帳戶屬性 (Property)。嗯...到那時,大概也到了該吃午餐的時候了!

首先介紹能防止使用者變更自己密碼的指令碼:

Const ADS_UF_PASSWD_CANT_CHANGE = &H0040
Set objUser = GetObject("WinNT://atl-ws-01/kenmyer")
If Not objUser.UserFlags AND ADS_UF_PASSWD_CANT_CHANGE Then
    objPasswordNoChangeFlag = objUser.UserFlags XOR ADS_UF_PASSWD_CANT_CHANGE
    objUser.Put "userFlags", objPasswordNoChangeFlag 
    objUser.SetInfo
End If

我們一開始先定義一個常數 (用了一個容易記的名稱 ADS_UF_PASSWD_CANT_CHANGE),我們要用它來識別 userFlags 屬性 (Attribute) 中的適當「開關」。這個 userFlags 屬性 (Attribute) 是一種位元遮罩屬性 (Attribute),是一種含有多項屬性 (Property) 和屬性值 (Property Value) 的單一屬性 (Attribute)。您可以將位元遮罩想像成一排開關,每一個開關代表一種不同的屬性 (Property)。如果代表「使用者不可變更密碼」的開關是開啟狀態,那麼使用者就不能變更他們的密碼;如果這個開關是關閉的,使用者就「可以」變更他們的密碼。這一部份應該是一看就懂了;比較麻煩的是,位元遮罩的「開關」並沒有像「使用者不可變更密碼」這樣的名稱。實際上它們是個十六進位的值,像是 &H0040。為了執行我們的工作,我們需要切換這個 &H0040 開關。這就是我們為什麼要定義這個常數的原因。

接下來,我們連線到電腦 atl-ws-01 上的 kenmyer 帳戶。這時候,我們要檢查看看這個開關是不是已經開啟了。在處理位元遮罩的時候,我們通常會看到類似下面的程式碼:

If objUser.UserFlags AND ADS_UF_PASSWD_CANT_CHANGE Then

用一般的話來講,這行程式碼就是說「如果 userFlags 屬性 (Attribute) 存在而且 ADS_UF_PASSWD_CANT_CHANGE 開關已經開啟了,表示這個陳述式為真,所以我們應該做某些事情」。在我們的例子中,我們對已經開啟的開關沒什麼興趣;因為如果「不可變更密碼」的旗標已經設定了,表示我們的工作已經完成。我們真正在乎的,是「關閉」的開關。因此,我們用了下面這行程式碼,它只會在開關「沒有」開啟的情況下採取動作:

If Not objUser.UserFlags AND ADS_UF_PASSWD_CANT_CHANGE Then

接下來,您可能更弄不清楚。仔細看看這行程式碼:

objPasswordNoChangeFlag = objUser.UserFlags XOR ADS_UF_PASSWD_CANT_CHANGE

實際上,如果不看外表,它其實是非常簡單的程式碼。我們在這裡做的,只不過是切換「使用者不可變更密碼」這個開關的數值。也就是 XOR 命令所執行的動作。如果這個開關是開啟的,XOR 會將它切換成關閉;如果它是關閉的,XOR 會將它開啟。我們要利用 userFlags 屬性目前的值,然後切換這個「使用者不可變更密碼」開關。由於我們知道這個開關是關閉狀態 (還記得我們剛才用的是 If Not 陳述式嗎?),所以 XOR 命令一定會將這個開關切換成開啟狀態。因此,變數 objPasswordNoChangeFlag 所包含的數值將會和目前 userFlags 屬性中的值完全相同,只有一個地方不一樣:「使用者不可變更密碼」這個開關現在是開啟狀態,而不是關閉。

聽得懂嗎?指令碼的其他部份都相當簡單。下面這行程式碼會將變數 objPasswordNoChangeFlag 的值寫入 userFlags 屬性:

objUser.Put "userFlags", objPasswordNoChangeFlag

接下來,我們用 SetInfo 命令將這些變更寫入使用者帳戶。一切搞定,本機使用者 Ken Myer 將不再擁有在電腦 atl-ws-01 上變更密碼的權限。

那麼,假如要「允許」Ken Myer 變更密碼又該怎麼做呢?喔...非常簡單。我們只要檢查「使用者不可變更密碼」這個開關是否為「開啟」狀態,然後用 XOR 將它關閉就可以了:

Const ADS_UF_PASSWD_CANT_CHANGE = &H0040
Set objUser = GetObject("WinNT://atl-ws-01/kenmyer")
If objUser.UserFlags AND ADS_UF_PASSWD_CANT_CHANGE Then
    objPasswordNoChangeFlag = objUser.UserFlags XOR ADS_UF_PASSWD_CANT_CHANGE
    objUser.Put "userFlags", objPasswordNoChangeFlag 
    objUser.SetInfo
End If

唯一的差異是我們從 If-Then 陳述式中拿掉了 Not 這個字。因為我們現在要找出開關已經開啟的情況,目的是要將它關閉。

的確,這些位元遮罩屬性確實不太容易搞懂。如果您還需要更詳細的資訊 (再加幾張圖片),您不妨試試《Microsoft Windows 2000 指令碼指南》(Microsoft Windows 2000 Scripting Guide) 中的這個部份 (英文)。前面說過,我們以下還要介紹一些可以用 userFlags 屬性 (Attribute) 管理的本機使用者帳戶屬性 (Property)。


屬性 (Property) 常數 數值
登入指令碼將會執行 ADS_UF_SCRIPT &H0001
帳戶已停用 ADS_UF_ACCOUNTDISABLE &H0002
帳戶需要主目錄 ADS_UF_HOMEDIR_REQUIRED &H0008
帳戶已鎖定 ADS_UF_LOCKOUT &H0010
帳戶不需要密碼 ADS_UF_PASSWD_NOTREQD &H0020
使用者不可變更密碼 ADS_UF_PASSWD_CANT_CHANGE &H0040
允許加密的文字密碼 ADS_UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED &H0080
密碼永久有效 ADS_UF_DONT_EXPIRE_PASSWD &H10000
登入時需要智慧卡 ADS_UF_SMARTCARD_REQUIRED &H40000
密碼已過期 ADS_UF_PASSWORD_EXPIRED &H800000


在您覺得無聊的時候,不妨將這些數值代入這個「使用者不可變更密碼」指令碼,看看會發生什麼狀況 (當然,就像以前一樣,建議您在實驗這類指令碼的時候,最好能使用測試電腦,最低限度也要用測試帳戶)。

 


如需詳細資訊

查看嗨,Scripting Guy!- 過往文件

 

回到頁首 回到頁首