ちょっとした質問があります...ユーザーのリストをデータベースに保存し、プログラムの起動時に、ユーザーがリストに含まれているか管理者であるかを比較してから使用させるプログラムがあります。現在、ユーザーが管理者であるかどうかを確認するために使用している方法は、ユーザー名を「ADMINISTRATOR」という文字列定数と比較することです。これは英語以外のシステムでも機能しますか? IE では、Windows は言語固有のバージョンの「管理者」を使用しますか? または、「ADMINISTRATOR」文字列の代わりにチェックに使用できる、列挙されたバージョンの管理者ユーザーが存在する可能性がありますか? (ご存知のように、Windows フォルダーが列挙される方法と同じです)。ところで、私は Delphi 2009 を使用しています。前もって感謝します!
5 に答える
いいえ、そのようにしないでください。きっと壊れます。ユーザーがメンバーになっているすべてのグループのリストを取得し、SIDの1つがS-1-5-32-544
AdministratorsグループのSIDであるかどうかを確認できます。よく知られているSIDのリストがあります。元の管理者アカウントのSIDもあります。
リストは次のとおりです。
ニュース
2010 年、@ChristianWimmer は私のコーディング スタイルを批判しました。2 年後、私は自分のプログラムでこの関数を再び使用する必要があります。そこで、関数のコーディング スタイルを改善することにしました。
概要
あなたの便宜のために、私のプライベート ライブラリのごく一部をピックアップします。アクセス トークンのユーザー アカウントがローカル管理者グループのメンバーであるかどうかをテストするには、eWellKnownSidTypeパラメーターWinBuiltinAdministratorsSid
にJwaWinNT
を渡します。Delphiユニットが を定義していないため、 JEDI API ライブラリが必要であることに注意してください。Windows.pas
CreateWellKnownSid()
実装
//------------------------------------------------------------------------------
// Purpose: Tests whether user account of the access token is a member of the
// specified well known group, and report its elevation type.
// Parameter:
// hToken [in,opt]
// A handle to an access token having TOKEN_QUERY and TOKEN_DUPLICATE
// access. If hToken is 0: if it is an impersonation token, the access token
// of the calling thread is used; otherwise, the access token associated
// with the process is used.
// eWellKnownSidType [in]
// Member of the WELL_KNOWN_SID_TYPE enumeration that specifies what Sid the
// function will identify.
// pDomainSid [in,opt]
// A pointer to a SID that identifies the domain to use when identifying the
// Sid. Pass nil to use the local computer.
// peElevType [out,opt]
// A pointer to a variable that receives the following elevation type of the
// access token:
// - TokenElevationTypeDefault: The access token does not have a linked
// token. This value is reported under Windows prior to Windows Vista.
// - TokenElevationTypeFull: The access token is an elevated token.
// - TokenElevationTypeLimited: The access token is a limited token.
// Return value:
// - True if user account of the access token is a member of the well known
// group specified in eWellKnownSidType parameter.
// - False, otherwise. To get error information, call GetLastError().
// Remarks:
// To test whether user account of the access token is a member of local
// administrators group, pass JwaWinNT.WinBuiltinAdministratorsSid to
// eWellKnownSidType parameter.
// References:
// - How To Determine Whether a Thread Is Running in User Context of
// Local Administrator Account [MSDN]
//------------------------------------------------------------------------------
function Inu_IsMemberOfWellKnownGroup(const hToken: Windows.THandle;
const eWellKnownSidType: JwaWinNT.WELL_KNOWN_SID_TYPE;
const pDomainSid: JwaWinNT.PSID=nil;
peElevType: PTokenElevationType=nil): Boolean;
var
hAccessToken: Windows.THandle;
rOSVerInfo: Windows.OSVERSIONINFO;
eTET: Windows.TTokenElevationType;
iReturnLen: Windows.DWORD;
hTokenToCheck: Windows.THandle;
iSidLen: Windows.DWORD;
pGroupSid: JwaWinNT.PSID;
bMemberOfWellKnownGroup: Windows.BOOL;
begin
Result := False;
hAccessToken := 0;
hTokenToCheck := 0;
pGroupSid := nil;
try
if hToken = 0 then begin // If the caller doesn't supply a token handle,
// Get the calling thread's access token
if not Windows.OpenThreadToken(Windows.GetCurrentThread(),
Windows.TOKEN_QUERY or Windows.TOKEN_DUPLICATE,
True, hAccessToken) then begin
if Windows.GetLastError() <> Windows.ERROR_NO_TOKEN then
Exit();
// If no thread token exists, retry against process token
if not Windows.OpenProcessToken(Windows.GetCurrentProcess(),
Windows.TOKEN_QUERY or Windows.TOKEN_DUPLICATE, hAccessToken) then
Exit();
end;
end
else // If the caller supplies a token handle,
hAccessToken := hToken;
// Determine whether the system is running Windows Vista or later because
// because they support linked tokens, previous versions don't.
rOSVerInfo.dwOSVersionInfoSize := SizeOf(Windows.OSVERSIONINFO);
if not Windows.GetVersionEx(rOSVerInfo) then
Exit();
if rOSVerInfo.dwMajorVersion >= 6 then begin
// Retrieve information about the elevation level of the access token
if not Windows.GetTokenInformation(hAccessToken,
Windows.TokenElevationType, @eTET,
SizeOf(Windows.TTokenElevationType), iReturnLen) then
Exit();
// If the access token is a limited token, retrieve the linked token
// information from the access token.
if eTET = Windows.TokenElevationTypeLimited then begin
if not Windows.GetTokenInformation(hAccessToken,
Windows.TokenLinkedToken, @hTokenToCheck,
SizeOf(Windows.TTokenLinkedToken), iReturnLen) then
Exit();
end;
// Report the elevation type if it is wanted
if Assigned(peElevType) then
peElevType^ := eTET;
end
else begin // if rOSVerInfo.dwMajorVersion < 6
// There is no concept of elevation prior to Windows Vista
if Assigned(peElevType) then
peElevType^ := Windows.TokenElevationTypeDefault;
end;
// CheckTokenMembership() requires an impersonation token. If we just got a
// linked token, it is already an impersonation token. Otherwise, duplicate
// the original as an impersonation token for CheckTokenMembership().
if (hTokenToCheck = 0) and (not Windows.DuplicateToken(hAccessToken,
Windows.SecurityIdentification, @hTokenToCheck)) then
Exit();
// Allocate enough memory for the longest possible Sid
iSidLen := JwaWinNT.SECURITY_MAX_SID_SIZE;
pGroupSid := JwaWinNT.PSid(Windows.LocalAlloc(Windows.LMEM_FIXED, iSidLen));
if not Assigned(pGroupSid) then
Exit();
// Create a Sid for the predefined alias as specified in eWellKnownSidType
if not JwaWinBase.CreateWellKnownSid(eWellKnownSidType, pDomainSid,
pGroupSid, iSidLen) then
Exit();
// Now, check presence of the created Sid in the user and group Sids of the
// access token. In other words, it determines whether the user is a member
// of the well known group specified in eWellKnownSidType parameter.
if not JwaWinBase.CheckTokenMembership(hTokenToCheck, pGroupSid,
bMemberOfWellKnownGroup) then
Exit();
Result := bMemberOfWellKnownGroup;
finally
// Close the access token handle
if hAccessToken <> 0 then
Windows.CloseHandle(hAccessToken);
// Close the new duplicate token handle if exists
if (hTokenToCheck <> 0) then
Windows.CloseHandle(hTokenToCheck);
// Free the allocated memory for the Sid created by CreateWellKnownSid()
if Assigned(pGroupSid) then
Windows.LocalFree(Windows.HLOCAL(pGroupSid));
end;
end; // endfunction Inu_IsMemberOfWellKnownGroup
//==============================================================================
これは、JEDI API&WSCLのJwsclToken.pasからの抜粋です。どちらの関数も同じチェックを行いますが、方法が異なります。コードがどれだけ使用されているかわかりますか?プレーンなWinAPIの同じコードは、少なくとも5倍大きくなります。もちろん、ユニット自体からこれらの関数を呼び出すこともできます。ここにコピーする必要はありません!
function JwCheckAdministratorAccess: boolean;
var
SD: TJwSecurityDescriptor;
begin
if not Assigned(JwAdministratorsSID) then
JwInitWellKnownSIDs;
SD := TJwSecurityDescriptor.Create;
try
SD.PrimaryGroup := JwNullSID;
SD.Owner := JwAdministratorsSID;
SD.OwnDACL := True;
SD.DACL.Add(TJwDiscretionaryAccessControlEntryAllow.Create(nil,
[], STANDARD_RIGHTS_ALL, JwAdministratorsSID, False));
Result := TJwSecureGeneralObject.AccessCheck(SD, nil,
STANDARD_RIGHTS_ALL, TJwSecurityGenericMapping);
finally
FreeAndNil(SD);
end;
end;
function JwIsMemberOfAdministratorsGroup: boolean;
var
Token: TJwSecurityToken;
begin
Token := TJwSecurityToken.CreateTokenEffective(TOKEN_READ or
TOKEN_DUPLICATE);
try
Token.ConvertToImpersonatedToken(SecurityImpersonation, MAXIMUM_ALLOWED);
Result := Token.CheckTokenMembership(JwAdministratorsSID)
finally
FreeAndNil(Token);
end;
end;
Windowsのバージョンによって異なります...pre-vistaでは...管理者のユーザー名はWindowsのプライマリ言語です...たとえば、スペイン語ではAdministradorです。
ポストビスタでは、管理者ユーザーは存在しません。ユーザー権限を保存して確認する必要があります。
私はこのIsAdmin関数を見つけました、そしてあなたもそれが役に立つと思うかもしれません...
CreateWellKnownSid関数があります。
ただし、管理者アカウントを明示的にチェックすることはお勧めできません。「アクセスが拒否されました」というエラーが発生した場合は、操作を実行して昇格を要求してください。