限制域中賬戶在不同計算機上重複登錄的腳本
在微軟的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中創建的這個登錄標識和密碼。在腳本中也需要使用到。
'**************下面是登錄腳本**************************************
'限制域中同賬戶重複登錄:用戶登錄腳本
'基本原理是在用戶登錄過程中,檢查數據庫(事先創建)中當前登錄賬戶和計算機信息,
'如果沒有當前登錄的用戶和計算機信息,則允許登錄;如果已經存在當前登錄的賬戶,則不予登錄
'當用戶註銷或關機,則運行註銷腳本,將登錄時記錄的信息從數據庫中刪除
'本腳本是登錄腳本
'作者:許震 [email protected]
'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
'********************下面是註銷腳本**********************************
'限制域中同賬戶重複登錄:用戶註銷腳本
'基本原理是在用戶登錄過程中,檢查數據庫(事先創建)中當前登錄賬戶和計算機信息,
'如果沒有當前登錄的用戶和計算機信息,則允許登錄;如果已經存在當前登錄的賬戶,則不予登錄
'當用戶註銷或關機,則運行註銷腳本,將登錄時記錄的信息從數據庫中刪除
'本腳本是註銷腳本
'作者:許震 [email protected]
'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
除非管理員能夠非常有耐心的設置每一個賬戶的登錄位置,並且從此以後這些賬戶的登錄計算機被固定死了。那麼如何達到限制賬戶同一時間只能登錄一臺計算機,並且登錄位置不限制呢?
微軟有一個軟件叫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中創建的這個登錄標識和密碼。在腳本中也需要使用到。
'**************下面是登錄腳本**************************************
'限制域中同賬戶重複登錄:用戶登錄腳本
'基本原理是在用戶登錄過程中,檢查數據庫(事先創建)中當前登錄賬戶和計算機信息,
'如果沒有當前登錄的用戶和計算機信息,則允許登錄;如果已經存在當前登錄的賬戶,則不予登錄
'當用戶註銷或關機,則運行註銷腳本,將登錄時記錄的信息從數據庫中刪除
'本腳本是登錄腳本
'作者:許震 [email protected]
'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
'********************下面是註銷腳本**********************************
'限制域中同賬戶重複登錄:用戶註銷腳本
'基本原理是在用戶登錄過程中,檢查數據庫(事先創建)中當前登錄賬戶和計算機信息,
'如果沒有當前登錄的用戶和計算機信息,則允許登錄;如果已經存在當前登錄的賬戶,則不予登錄
'當用戶註銷或關機,則運行註銷腳本,將登錄時記錄的信息從數據庫中刪除
'本腳本是註銷腳本
'作者:許震 [email protected]
'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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.