Мне нужно получить текущее имя пользователя? Мне нужно, чтобы это работало правильно, когда я вызываю код из ASP.NET, который работает в режиме проверки подлинности Windows. то есть я не хочу получить пользователя ASPNET в этом случае, а олицетворенного пользователя. Это связано с моим более ранним вопросом. Все, что я пытаюсь сделать, возвращает ASPNET.
Как получить текущего вошедшего в систему пользователя, включая домен в Delphi 2009?
Ответы (3)
В другом вопросе вы написали, что настроили ASP.NET для использования проверки подлинности Windows с олицетворением:
<system.web>
...
<authentication mode="Windows"/>
<identity impersonate="true"/>
...
</system.web>
Отображает ли приложение ASP.NET правильные учетные данные (пользователя и домена)?
Вы вызываете функцию Delphi, используя правильный контекст Identity, например
WindowsIdentity winId = (WindowsIdentity)HttpContext.Current.User.Identity;
try
{
ctx = winId.Impersonate();
// call Delphi function, passing the identity context
}
catch
{
}
finally
{
if (ctx != null)
ctx.Undo();
}
Обновлять:
Если объект COM вызывается из кода для страницы веб-формы, вы можете попытаться установить для свойства ASPCOMPAT страницы веб-формы значение true.
Видеть:
Тег «identity» гарантирует, что поток, выполняющий запрос (поток MTA), будет олицетворять свой контекст безопасности для пользователя, указанного в теге, но наш STA COM-объект в конечном итоге был создан в потоке STA по умолчанию, который не был олицетворенным, что привело к чтобы получить контекст безопасности процесса (это был IUSR_XXX — наименее влиятельный пользователь из всех).
Возможно, ваш подход IADsWinNTSystemInfo (из связанного предыдущего вопроса) возвращает информацию об учетной записи текущего процесса, но ASP.NET выдает себя за уровень потока?
Попробуй это:
type
PTokenUser = ^TTokenUser;
TTokenUser = packed record
User: SID_AND_ATTRIBUTES;
end;
function GetCurrentUserName(out DomainName, UserName: string): Boolean;
var
Token: THandle;
InfoSize, UserNameSize, DomainNameSize: Cardinal;
User: PTokenUser;
Use: SID_NAME_USE;
_DomainName, _UserName: array[0..255] of Char;
begin
Result := False;
DomainName := '';
UserName := '';
Token := 0;
if not OpenThreadToken(GetCurrentThread, TOKEN_QUERY, True, Token) then
begin
if GetLastError = ERROR_NO_TOKEN then // current thread is not impersonating, try process token
begin
if not OpenProcessToken(GetCurrentProcess, TOKEN_QUERY, Token) then
Exit;
end
else
Exit;
end;
try
GetTokenInformation(Token, TokenUser, nil, 0, InfoSize);
User := AllocMem(InfoSize * 2);
try
if GetTokenInformation(Token, TokenUser, User, InfoSize * 2, InfoSize) then
begin
DomainNameSize := SizeOf(_DomainName);
UserNameSize := SizeOf(_UserName);
Result := LookupAccountSid(nil, User^.User.Sid, _UserName, UserNameSize, _DomainName, DomainNameSize, Use);
if Result then
begin
SetString(DomainName, _DomainName, StrLen(_DomainName));
SetString(UserName, _UserName, StrLen(_UserName));
end;
end;
finally
FreeMem(User);
end;
finally
CloseHandle(Token);
end;
end;
Пример использования:
var
DomainName, UserName: string;
begin
if not GetCurrentUserName(DomainName, UserName) then
RaiseLastOSError;
Writeln(Format('%s\%s', [DomainName, UserName]));
end;
Надеюсь это поможет.
Это часть кода моего LoadProfile, он хорошо работает в Delphi 2010:
const
UNLEN = 256; // Maximum user name length
var
TokenHandle: THandle; // Handle to the Processes' Acces Token
cbTokenInfo: DWORD; // Size of TokenInfo in Bytes
pTokenUser: PTOKEN_USER; // Pointer to a TOKEN_USER record
cchName: DWORD; // Count of characters (length) of the Username array
cchDomain: DWORD; // Count of characters (length) of the Domainname array
peUse: DWORD; // Account type for LookupAccountSid
UserName: array[0..UNLEN] of Char; // Holds the Username
DomainName: array[0..UNLEN] of Char; // Holds the Domainname
ComputerName: array[0..UNLEN] of Char; // Hold the Computername
// Open the Current Process' Token
OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY or
TOKEN_IMPERSONATE or TOKEN_DUPLICATE, TokenHandle);
// Check if we have a valid handle
if TokenHandle = 0 then
Exit;
{ We will use GetTokenInformation to get the user's SID, the first call
to GetTokenInformation is used to determine how much memory we need to
allocate }
GetTokenInformation(TokenHandle, TokenUser, nil, 0, cbTokenInfo);
// as documented the call should fail with ERROR_INSUFFICIENT_BUFFER
if (GetLastError() <> ERROR_INSUFFICIENT_BUFFER) then
Exit;
// Allocate Memory
pTokenUser := HeapAlloc(GetProcessHeap(), 0, cbTokenInfo);
if (pTokenUser = nil) then
Exit;
// Retrieve the user information from the token.
if ( not GetTokenInformation(TokenHandle, TokenUser, pTokenUser,
cbTokenInfo, cbTokenInfo)) then
Exit;
cchName := Length(UserName);
cchDomain := Length(DomainName);
peUse:= SidTypeUser;
// Use the SID to find User and Domain Name
Write('LookupAccountSid... ');
if not LookupAccountSid(nil, pTokenUser^.User.Sid, UserName, cchName,
DomainName, cchDomain, peUse) then
Exit;
// Cleanup
if (pTokenUser <> nil) then
HeapFree(GetProcessHeap(), 0, pTokenUser);
WriteLn('CloseHandle... OK');
CloseHandle(TokenHandle);