在微軟的AD域中,任何一個用戶帳戶均可以在不一樣的客戶機上登陸,有時甚至同一個帳戶同一個時間在不一樣的計算機上重複登陸。微軟AD自帶的帳戶控制功能「登陸到」設置僅僅能控制某一個帳戶在某一臺(或多臺)計算機上登陸,可是並不能控制整個域中全部帳戶的重複登陸。
除非管理員可以很是有耐心的設置每個帳戶的登陸位置,而且今後之後這些帳戶的登陸計算機被固定死了。那麼如何達到限制帳戶同一時間只能登陸一臺計算機,而且登陸位置不限制呢?
微軟有一個軟件叫LimitLogon,可是須要至少一臺服務器做爲 Web Server,須要擴展架構,建立一個應用程序分區(會影響恢復速度)。客戶端須要Dotnet 1.1和安裝一個客戶端軟件以支持SAOP和Web Server通信。這些條件通常公司很難接受。還有一個第三方軟件叫UserLock,很好很強大,可是收費的。
如今用腳原本實現這個功能,基本思想是這樣的:
1。當用戶登陸時,檢查數據庫中全部當前用戶登陸記錄,若是沒有該帳戶信息,容許登陸,並記錄登陸帳戶、客戶機位置和時間;
2。當另外一個用戶使用一樣的帳戶登陸時,進行一樣的檢查,因爲已經有登陸的信息記錄,說明如今登陸的帳戶是重複登陸,則禁止登陸;
3。當用戶註銷或關機時,運行註銷腳本,將數據庫中的登陸信息進行刪除以備下一次登陸;
4。若是因爲網絡緣由或客戶機異常關機,致使註銷或關機時用戶登陸信息沒有正常刪除,影響下一次登陸,所以在登陸檢查時,若是當前登陸的帳戶和客戶機與數據庫中的信息是一致的,說明是同一個帳戶在同一個計算機上登陸,仍然容許登陸,僅僅是更新數據庫中的登陸時間信息。
原來實現方法是使用一個文本文件做爲登陸信息的記錄,可是發現當登陸用戶較多時,因爲文本的單用戶操做性,多個用戶不能同時進行登陸信息的記錄,形成登陸延遲,所以改用SQL Server(也能夠是MSDE)進行登陸信息的記錄。若是使用Access數據庫,因爲Access仍然是單用戶的,能夠在前端使用一個Web接受用戶登陸信息(相似於某些網站)。可是進行Web的開發還不如使用MSDE簡單,這裏就不作解釋了。
說明:
1。首先要找一個SQL Server服務器,建立一個數據庫(或使用現有數據庫),在裏面建立一個表adlogin,表結構以下:
create table adlogin
(currentloginuser varchar(20),
currentloginpc varchar(20),
logintime datetime)
這裏須要記住服務器、數據庫和表的名稱,在腳本中須要用到。
2。因爲腳本是用戶登陸/註銷腳本,所以是用當前登陸用戶的帳戶權限運行的,若是SQL Server採用「僅Windows身份認證」須要該帳戶可以訪問SQL Server並在上述表中添加或刪除記錄,所以須要將SQL Server的安全模式改成混合模式,而且建立一個SQL登陸標識並設定密碼。
固然能夠在數據庫中進行權限設置,使該帳戶僅僅可以訪問上述表,而不是整個數據庫。這一點在SQL Server安全中尤爲重要!
記住SQL Server中建立的這個登陸標識和密碼。在腳本中也須要使用到。
'**************下面是登陸腳本**************************************
'限制域中同帳戶重複登陸:用戶登陸腳本
'基本原理是在用戶登陸過程當中,檢查數據庫(事先建立)中當前登陸帳戶和計算機信息,
'若是沒有當前登陸的用戶和計算機信息,則容許登陸;若是已經存在當前登陸的帳戶,則不予登陸
'當用戶註銷或關機,則運行註銷腳本,將登陸時記錄的信息從數據庫中刪除
'本腳本是登陸腳本
'做者:許震
v-zhenxu@microsoft.com
'2008-3-11
On Error Resume Next
Const adOpenStatic = 3
Const adLockOptimistic = 3
Const adUseClient = 3
Const E_Recordset_Not_Found=&h800A0BCD
Set obj = WScript.CreateObject("WScript.Shell")
Set WshNetwork = WScript.CreateObject("WScript.Network")
Set objConnection = CreateObject("ADODB.Connection")
Set objRecordSet = CreateObject("ADODB.Recordset")
'得到當前登陸的用戶帳戶和計算機名
CurrentUserName=WshNetwork.UserName
CurrentPcName=WshNetwork.ComputerName
'鏈接到SQL Server並打開相應的數據庫
'Data Source=win2k3指定SQL Server服務器名
'Trusted_Connection=no表示使用SQL身份認證鏈接,這是必須的
'Initial Catalog=Northwind指定數據庫
'User ID=limiteduser;Password=pass01!指定數據庫鏈接帳戶和密碼
objConnection.Open _
"Provider=SQLOLEDB;Data Source=win2k3;" & _
"Trusted_Connection=no;Initial Catalog=Northwind;" & _
"User ID=limiteduser;Password=pass01!;"
objRecordset.CursorLocation = adUseClient
'得到adlogin表中的全部記錄,注意根據實際狀況使用表名
objRecordSet.Open "SELECT * FROM adlogin", _
objConnection, adOpenStatic, adLockOptimistic
IF err.number = E_Recordset_Not_Found Then
Wscript.Echo "no table!"
script.Quit 1
End If
'在結果集中查詢currentloginuser字段包含當前登陸帳戶的記錄
strSearchCriteria = "currentloginuser = '" & CurrentUserName & "'"
objRecordSet.Find strSearchCriteria
'若是結果集中沒有當前用戶記錄,說明該帳戶目前沒有人使用,
'容許用戶登陸並在數據庫中記錄當前用戶、計算機和登陸時間
If objRecordset.EOF Then
objRecordSet.AddNew
objRecordSet("currentloginuser") = UCase(CurrentUserName)
objRecordSet("currentloginpc") = UCase(CurrentPcName)
objRecordSet("logintime") = now()
objRecordSet.Update
'若是結果集中有當前登陸用戶記錄,說明該帳戶已經有人在使用,分兩種狀況處理
Else
'再檢查當前登陸計算機名稱,若是和數據庫中的計算機記錄不一致,說明是使用同一個帳戶在不一樣計算機上登陸,
'顯示提示信息,並強制用戶註銷
If UCase(objRecordset.Fields.Item("currentloginpc")) <> UCase(CurrentPcName) Then
'在這裏存在一個風險,當彈出警告信息框時,若是用戶無論這個提示,而是直接調用任務管理器殺掉腳本宿主進程,
'則能夠繞過登陸限制,所以爲了杜絕這個漏洞,能夠將下面3行顯示警告框的部分刪除。
'這樣能夠不給客戶調用任務管理器的機會,除非客戶是閃電俠
WScript.Echo "The user account " & objRecordset.Fields.Item("currentloginuser") & " has login on " & _
objRecordset.Fields.Item("currentloginpc") & _
", so you can't login using the same user account. Please call the administrator!"
obj.Run "logoff"
'若是當前登陸計算機名稱和數據庫中一致,說明是同一個帳戶在同一臺計算機上登陸,容許登陸並更新數據庫登陸時間
'這主要是爲了防止計算機非正常關機致使在數據庫中的信息沒有正常刪除,形成用戶不能登陸
'所以若是客戶機非正常關機,或網絡緣由,只要下次登陸仍然在同一臺計算機,仍舊能夠登陸,只是登陸時間更新
Else
objRecordSet("logintime") = now()
objRecordSet.Update
End If
End If
objRecordSet.Close
objConnection.Close
'********************下面是註銷腳本**********************************
'限制域中同帳戶重複登陸:用戶註銷腳本
'基本原理是在用戶登陸過程當中,檢查數據庫(事先建立)中當前登陸帳戶和計算機信息,
'若是沒有當前登陸的用戶和計算機信息,則容許登陸;若是已經存在當前登陸的帳戶,則不予登陸
'當用戶註銷或關機,則運行註銷腳本,將登陸時記錄的信息從數據庫中刪除
'本腳本是註銷腳本
'做者:許震
v-zhenxu@microsoft.com '2008-3-11 On Error Resume Next Const adOpenStatic = 3 Const adLockOptimistic = 3 Const adUseClient = 3 Const E_Recordset_Not_Found=&h800A0BCD Set objConnection = CreateObject("ADODB.Connection") Set objRecordSet = CreateObject("ADODB.Recordset") Set WshNetwork = WScript.CreateObject("WScript.Network") '得到當前登陸的用戶帳戶和計算機名 CurrentUserName=WshNetwork.UserName CurrentPcName=WshNetwork.ComputerName '鏈接到SQL Server並打開相應的數據庫 'Data Source=win2k3指定SQL Server服務器名 'Trusted_Connection=no表示使用SQL身份認證鏈接,這是必須的 'Initial Catalog=Northwind指定數據庫 'User ID=limiteduser;Password=pass01!指定數據庫鏈接帳戶和密碼 objConnection.Open _ "Provider=SQLOLEDB;Data Source=win2k3;" & _ "Trusted_Connection=No;Initial Catalog=Northwind;" & _ "User ID=limiteduser;Password=pass01!;" objRecordset.CursorLocation = adUseClient objRecordSet.Open "SELECT * FROM adlogin", _ objConnection, adOpenStatic, adLockOptimistic IF err.number = E_Recordset_Not_Found Then Wscript.Echo "no table!" script.Quit 1 End If '在結果集中查詢currentloginuser字段包含當前登陸帳戶的記錄 strSearchCriteria = "currentloginuser = '" & CurrentUserName & "'" objRecordSet.Find strSearchCriteria '刪除該用戶的登陸記錄 If UCase(objRecordset.Fields.Item("currentloginpc")) = UCase(CurrentPcName) Then objRecordset.Delete End If objRecordSet.Close objConnection.Close