你目前正处于脱机状态,正在等待 Internet 重新连接

如何验证用户凭据的 Microsoft 操作系统上

注意:这篇文章是由无人工介入的微软自动的机器翻译软件翻译完成。微软很高兴能同时提供给您由人工翻译的和由机器翻译的文章, 以使您能使用您的语言访问所有的知识库文章。然而由机器翻译的文章并不总是完美的。它可能存在词汇,语法或文法的问题,就像是一个外国人在说中文时总是可能犯这样的错误。虽然我们经常升级机器翻译软件以提高翻译质量,但是我们不保证机器翻译的正确度,也不对由于内容的误译或者客户对它的错误使用所引起的任何直接的, 或间接的可能的问题负责。

点击这里察看该文章的英文版: 180548
概要
偶尔,您可能想要验证用户的用户名和密码 (以后指凭据) 的应用程序。您可以执行这两种取决于应用程序在其运行的操作系统的不同方法。

本文介绍了常用的方法来验证用户的凭据和特殊的要求,对于每个方法的所有。

注意从用户模式应用程序收集用户凭据可能会令人讨厌的用户,并且可以提供企业计算环境中可能的安全漏洞。这些原因非常统一登录要求 (用户应该只需要在 CTRL + ALT + DEL 屏幕中键入其凭据一次一个要求) 添加到 Microsoft BackOffice 徽标要求。它是要确保您真正需要收集凭据和客户端/服务器验证的一些其他方法不是更合适。有关模拟和编程安全的服务器的详细信息,请参阅平台 SDK 中的安全文档。
更多信息
LogonUser API 后可用,并记录在案 Windows NT 3.51 的通常用来验证用户凭据。此 API 是 Windows NT、 Windows 2000 和 Windows XP 中可用。遗憾的是,有对使用 LogonUser 并不总是方便地满足某些限制。

第一个和最大的这些限制是在 Windows NT 和 Windows 2000,呼叫 LogonUser 过程都必须具有 SE_TCB_NAME 特权 (在用户管理器中这是在"作为操作系统的一部分"权限)。SE_TCB_NAME 权限是功能非常强大,应不授予任何任意的用户只需,以便他们可以运行的应用程序需要验证凭据。建议的方法是在本地系统帐户中运行的服务从调用 LogonUser,因为本地系统帐户已经具有 SE_TCB_NAME 特权。

注意LogonUser Win32 API 不需要 TCB 特权在 Microsoft Windows Server 2003 年但是,下层兼容这仍是最好的方法。

在 Windows XP 上就不再需要一个进程来调用 LogonUser 有 SE_TCB_NAME 特权。因此,最简单的方法来验证在 Windows XP 上的用户的凭据就是调用 LogonUser API。

一个其他 LogonUser 问题是 API 未在 Windows 95、 Windows 98 或 Windows Millennium 版上实现。

作为另一个的选项,您可以使用安全支持提供程序接口 (SSPI) 如何与网络样式登录提供用户凭据。 这种验证的方法有不需要任何特殊的权限,以及在所有版本的 Windows 上正常工作的优点。使用 SSPI 服务验证凭据的最终结果是一个类似于与 LOGON32_LOGON_NETWORK 登录类型调用 LogonUser API 的登录。这种类型的登录将最大缺点是无法访问远程网络模拟类型的网络登录后的资源。如果您的应用程序调用 LogonUser LOGON32_LOGON_INTERACTIVE 登录类型,以解决 Windows NT 无法执行委派然后与该 SSPI 登录/验证将可能不是一个可行的替代方案。

下面提供的代码示例演示如何调用 SSPI 服务以执行验证的凭据。

若要使用此方法在 Windows 95、 Windows 98 和 Windows Millennium 版,您还必须通过打开控制面板、 网络、 访问控制,然后选择用户级访问控制启用 NTLM 安全服务。

在 Windows XP 上 ForceGuest 注册表值设置为 1 默认情况下,在下面的注册表项中:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa
Windows XP 的计算机上的是工作组的成员:
  • 如果启用了 ForceGuest (1 设置) SSPI 将总是尝试使用来宾帐户登录。
  • 如果启用来宾帐户,则将作为来宾中 任何 用户凭据成功的 SSPI 登录。
  • 如果禁用来宾帐户,则一个 SSPI 登录将失败更有效的凭据。
  • 如果禁用 ForceGuest (0 到设置) SSPI 将指定的用户身份登录。
此外,如果启用来宾帐户,则 SSPI 登录可能成功作为来宾是无效的用户凭据。在这篇文章中的代码 C 的示例演示了如何,您可以检查已建立的安全上下文的存取令牌。IsGuest helper 函数,在示例代码显示了如何验证登录为指定的用户或来宾所发生的。

示例代码

///////////////////////////////////////////////////////////////////////////////////  SSPI Authentication Sample////  This program demonstrates how to use SSPI to authenticate user credentials.////  THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF//  ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED//  TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A//  PARTICULAR PURPOSE.////  Copyright (C) 2007.  Microsoft Corporation.  All rights reserved.///////////////////////////////////////////////////////////////////////////////#define SECURITY_WIN32#include <windows.h>#include <tchar.h>#include <stdio.h>#include <conio.h>#include <sspi.h>#include <lm.h>#include <lmcons.h>// Older versions of WinError.h do not have SEC_I_COMPLETE_NEEDED #define.// So, in such an SDK environment setup, we will include issperr.h which has the// definition for SEC_I_COMPLETE_NEEDED. Include issperr.h only if// SEC_I_COMPLETE_NEEDED is not defined.#ifndef SEC_I_COMPLETE_NEEDED#include <issperr.h>#endiftypedef struct _AUTH_SEQ {   BOOL fInitialized;   BOOL fHaveCredHandle;   BOOL fHaveCtxtHandle;   CredHandle hcred;   struct _SecHandle hctxt;} AUTH_SEQ, *PAUTH_SEQ;// Function pointersACCEPT_SECURITY_CONTEXT_FN       _AcceptSecurityContext     = NULL;ACQUIRE_CREDENTIALS_HANDLE_FN    _AcquireCredentialsHandle  = NULL;COMPLETE_AUTH_TOKEN_FN           _CompleteAuthToken         = NULL;DELETE_SECURITY_CONTEXT_FN       _DeleteSecurityContext     = NULL;FREE_CONTEXT_BUFFER_FN           _FreeContextBuffer         = NULL;FREE_CREDENTIALS_HANDLE_FN       _FreeCredentialsHandle     = NULL;INITIALIZE_SECURITY_CONTEXT_FN   _InitializeSecurityContext = NULL;QUERY_SECURITY_PACKAGE_INFO_FN   _QuerySecurityPackageInfo  = NULL;QUERY_SECURITY_CONTEXT_TOKEN_FN  _QuerySecurityContextToken = NULL;#define CheckAndLocalFree(ptr) \            if (ptr != NULL) \            { \               LocalFree(ptr); \               ptr = NULL; \            }#pragma comment(lib, "netapi32.lib")LPVOID RetrieveTokenInformationClass(      HANDLE hToken,      TOKEN_INFORMATION_CLASS InfoClass,      LPDWORD lpdwSize){   LPVOID pInfo = NULL;   BOOL fSuccess = FALSE;   __try   {      *lpdwSize = 0;      //      // Determine the size of the buffer needed      //      GetTokenInformation(            hToken,            InfoClass,            NULL,            *lpdwSize, lpdwSize);      if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)      {         _tprintf(_T("GetTokenInformation failed with %d\n"), GetLastError());         __leave;      }      //      // Allocate a buffer for getting token information      //      pInfo = LocalAlloc(LPTR, *lpdwSize);      if (pInfo == NULL)      {         _tprintf(_T("LocalAlloc failed with %d\n"), GetLastError());         __leave;      }      if (!GetTokenInformation(            hToken,            InfoClass,            pInfo,            *lpdwSize, lpdwSize))      {         _tprintf(_T("GetTokenInformation failed with %d\n"), GetLastError());         __leave;      }      fSuccess = TRUE;   }   __finally   {      // Free pDomainAndUserName only if failed      // Otherwise, the caller has to free after use      if (fSuccess == FALSE)      {         CheckAndLocalFree(pInfo);      }   }   return pInfo;}PSID GetUserSidFromWellKnownRid(DWORD Rid){    PUSER_MODALS_INFO_2 umi2;    NET_API_STATUS nas;    UCHAR SubAuthorityCount;    PSID pSid = NULL;    BOOL bSuccess = FALSE; // assume failure    nas = NetUserModalsGet(NULL, 2, (LPBYTE *)&umi2);    if (nas != NERR_Success)    {        printf("NetUserModalsGet failed with error code : [%d]\n", nas);        SetLastError(nas);        return NULL;    }    SubAuthorityCount = *GetSidSubAuthorityCount                       (umi2->usrmod2_domain_id);    //     // Allocate storage for new Sid. account domain Sid + account Rid    //     pSid = (PSID)LocalAlloc(LPTR,          GetSidLengthRequired((UCHAR)(SubAuthorityCount + 1)));    if (pSid != NULL)    {        if (InitializeSid(              pSid,              GetSidIdentifierAuthority(umi2->usrmod2_domain_id),              (BYTE)(SubAuthorityCount+1)              ))        {            DWORD SubAuthIndex = 0;            //             // Copy existing subauthorities from account domain Sid into            // new Sid            //             for (; SubAuthIndex < SubAuthorityCount ; SubAuthIndex++)            {                *GetSidSubAuthority(pSid, SubAuthIndex) =                *GetSidSubAuthority(umi2->usrmod2_domain_id,                                  SubAuthIndex);            }            //             // Append Rid to new Sid            //             *GetSidSubAuthority(pSid, SubAuthorityCount) = Rid;        }    }    NetApiBufferFree(umi2);    return pSid;}BOOL IsGuest(HANDLE hToken){    BOOL fGuest = FALSE;    PSID pGuestSid = NULL;    PSID pUserSid = NULL;    TOKEN_USER *pUserInfo = NULL;    DWORD dwSize = 0;    pGuestSid = GetUserSidFromWellKnownRid(DOMAIN_USER_RID_GUEST);    if (pGuestSid == NULL)        return fGuest;    //    // Get user information    //    pUserInfo = (TOKEN_USER *)RetrieveTokenInformationClass(hToken, TokenUser, &dwSize);    if (pUserInfo != NULL)    {        if (EqualSid(pGuestSid, pUserInfo->User.Sid))            fGuest = TRUE;    }    CheckAndLocalFree(pUserInfo);    CheckAndLocalFree(pGuestSid);    return fGuest;}///////////////////////////////////////////////////////////////////////////////void UnloadSecurityDll(HMODULE hModule) {   if (hModule)      FreeLibrary(hModule);   _AcceptSecurityContext      = NULL;   _AcquireCredentialsHandle   = NULL;   _CompleteAuthToken          = NULL;   _DeleteSecurityContext      = NULL;   _FreeContextBuffer          = NULL;   _FreeCredentialsHandle      = NULL;   _InitializeSecurityContext  = NULL;   _QuerySecurityPackageInfo   = NULL;   _QuerySecurityContextToken  = NULL;}///////////////////////////////////////////////////////////////////////////////HMODULE LoadSecurityDll() {   HMODULE hModule;   BOOL    fAllFunctionsLoaded = FALSE;   TCHAR   lpszDLL[MAX_PATH];   OSVERSIONINFO VerInfo;   //   //  Find out which security DLL to use, depending on   //  whether we are on Windows NT or Windows 95, Windows 2000, Windows XP, or Windows Server 2003   //  We have to use security.dll on Windows NT 4.0.   //  All other operating systems, we have to use Secur32.dll   //   VerInfo.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);   if (!GetVersionEx (&VerInfo))   // If this fails, something has gone wrong   {      return FALSE;   }   if (VerInfo.dwPlatformId == VER_PLATFORM_WIN32_NT &&      VerInfo.dwMajorVersion == 4 &&      VerInfo.dwMinorVersion == 0)   {      lstrcpy (lpszDLL, _T("security.dll"));   }   else   {      lstrcpy (lpszDLL, _T("secur32.dll"));   }   hModule = LoadLibrary(lpszDLL);   if (!hModule)      return NULL;   __try {      _AcceptSecurityContext = (ACCEPT_SECURITY_CONTEXT_FN)            GetProcAddress(hModule, "AcceptSecurityContext");      if (!_AcceptSecurityContext)         __leave;#ifdef UNICODE      _AcquireCredentialsHandle = (ACQUIRE_CREDENTIALS_HANDLE_FN)            GetProcAddress(hModule, "AcquireCredentialsHandleW");#else      _AcquireCredentialsHandle = (ACQUIRE_CREDENTIALS_HANDLE_FN)            GetProcAddress(hModule, "AcquireCredentialsHandleA");#endif      if (!_AcquireCredentialsHandle)         __leave;      // CompleteAuthToken is not present on Windows 9x Secur32.dll      // Do not check for the availablity of the function if it is NULL;      _CompleteAuthToken = (COMPLETE_AUTH_TOKEN_FN)            GetProcAddress(hModule, "CompleteAuthToken");      _DeleteSecurityContext = (DELETE_SECURITY_CONTEXT_FN)            GetProcAddress(hModule, "DeleteSecurityContext");      if (!_DeleteSecurityContext)         __leave;      _FreeContextBuffer = (FREE_CONTEXT_BUFFER_FN)            GetProcAddress(hModule, "FreeContextBuffer");      if (!_FreeContextBuffer)         __leave;      _FreeCredentialsHandle = (FREE_CREDENTIALS_HANDLE_FN)            GetProcAddress(hModule, "FreeCredentialsHandle");      if (!_FreeCredentialsHandle)         __leave;#ifdef UNICODE      _InitializeSecurityContext = (INITIALIZE_SECURITY_CONTEXT_FN)            GetProcAddress(hModule, "InitializeSecurityContextW");#else      _InitializeSecurityContext = (INITIALIZE_SECURITY_CONTEXT_FN)            GetProcAddress(hModule, "InitializeSecurityContextA");#endif      if (!_InitializeSecurityContext)         __leave;#ifdef UNICODE      _QuerySecurityPackageInfo = (QUERY_SECURITY_PACKAGE_INFO_FN)            GetProcAddress(hModule, "QuerySecurityPackageInfoW");#else      _QuerySecurityPackageInfo = (QUERY_SECURITY_PACKAGE_INFO_FN)            GetProcAddress(hModule, "QuerySecurityPackageInfoA");#endif      if (!_QuerySecurityPackageInfo)         __leave;      _QuerySecurityContextToken = (QUERY_SECURITY_CONTEXT_TOKEN_FN)            GetProcAddress(hModule, "QuerySecurityContextToken");      if (!_QuerySecurityContextToken)         __leave;      fAllFunctionsLoaded = TRUE;   } __finally {      if (!fAllFunctionsLoaded) {         UnloadSecurityDll(hModule);         hModule = NULL;      }   }   return hModule;}///////////////////////////////////////////////////////////////////////////////BOOL GenClientContext(PAUTH_SEQ pAS, PSEC_WINNT_AUTH_IDENTITY pAuthIdentity,      PVOID pIn, DWORD cbIn, PVOID pOut, PDWORD pcbOut, PBOOL pfDone) {/*++ Routine Description:   Optionally takes an input buffer coming from the server and returns   a buffer of information to send back to the server.  Also returns   an indication of whether or not the context is complete. Return Value:   Returns TRUE if successful; otherwise FALSE.--*/   SECURITY_STATUS ss;   TimeStamp       tsExpiry;   SecBufferDesc   sbdOut;   SecBuffer       sbOut;   SecBufferDesc   sbdIn;   SecBuffer       sbIn;   ULONG           fContextAttr;   if (!pAS->fInitialized) {      ss = _AcquireCredentialsHandle(NULL, _T("NTLM"),            SECPKG_CRED_OUTBOUND, NULL, pAuthIdentity, NULL, NULL,            &pAS->hcred, &tsExpiry);      if (ss < 0) {         fprintf(stderr, "AcquireCredentialsHandle failed with %08X\n", ss);         return FALSE;      }      pAS->fHaveCredHandle = TRUE;   }   // Prepare output buffer   sbdOut.ulVersion = 0;   sbdOut.cBuffers = 1;   sbdOut.pBuffers = &sbOut;   sbOut.cbBuffer = *pcbOut;   sbOut.BufferType = SECBUFFER_TOKEN;   sbOut.pvBuffer = pOut;   // Prepare input buffer   if (pAS->fInitialized)  {      sbdIn.ulVersion = 0;      sbdIn.cBuffers = 1;      sbdIn.pBuffers = &sbIn;      sbIn.cbBuffer = cbIn;      sbIn.BufferType = SECBUFFER_TOKEN;      sbIn.pvBuffer = pIn;   }   ss = _InitializeSecurityContext(&pAS->hcred,         pAS->fInitialized ? &pAS->hctxt : NULL, NULL, 0, 0,         SECURITY_NATIVE_DREP, pAS->fInitialized ? &sbdIn : NULL,         0, &pAS->hctxt, &sbdOut, &fContextAttr, &tsExpiry);   if (ss < 0)  {      // <winerror.h>      fprintf(stderr, "InitializeSecurityContext failed with %08X\n", ss);      return FALSE;   }   pAS->fHaveCtxtHandle = TRUE;   // If necessary, complete token   if (ss == SEC_I_COMPLETE_NEEDED || ss == SEC_I_COMPLETE_AND_CONTINUE) {      if (_CompleteAuthToken) {         ss = _CompleteAuthToken(&pAS->hctxt, &sbdOut);         if (ss < 0)  {            fprintf(stderr, "CompleteAuthToken failed with %08X\n", ss);            return FALSE;         }      }      else {         fprintf (stderr, "CompleteAuthToken not supported.\n");         return FALSE;      }   }   *pcbOut = sbOut.cbBuffer;   if (!pAS->fInitialized)      pAS->fInitialized = TRUE;   *pfDone = !(ss == SEC_I_CONTINUE_NEEDED         || ss == SEC_I_COMPLETE_AND_CONTINUE );   return TRUE;}///////////////////////////////////////////////////////////////////////////////BOOL GenServerContext(PAUTH_SEQ pAS, PVOID pIn, DWORD cbIn, PVOID pOut,      PDWORD pcbOut, PBOOL pfDone) {/*++ Routine Description:    Takes an input buffer coming from the client and returns a buffer    to be sent to the client.  Also returns an indication of whether or    not the context is complete. Return Value:    Returns TRUE if successful; otherwise FALSE.--*/   SECURITY_STATUS ss;   TimeStamp       tsExpiry;   SecBufferDesc   sbdOut;   SecBuffer       sbOut;   SecBufferDesc   sbdIn;   SecBuffer       sbIn;   ULONG           fContextAttr;   if (!pAS->fInitialized)  {      ss = _AcquireCredentialsHandle(NULL, _T("NTLM"),            SECPKG_CRED_INBOUND, NULL, NULL, NULL, NULL, &pAS->hcred,            &tsExpiry);      if (ss < 0) {         fprintf(stderr, "AcquireCredentialsHandle failed with %08X\n", ss);         return FALSE;      }      pAS->fHaveCredHandle = TRUE;   }   // Prepare output buffer   sbdOut.ulVersion = 0;   sbdOut.cBuffers = 1;   sbdOut.pBuffers = &sbOut;   sbOut.cbBuffer = *pcbOut;   sbOut.BufferType = SECBUFFER_TOKEN;   sbOut.pvBuffer = pOut;   // Prepare input buffer   sbdIn.ulVersion = 0;   sbdIn.cBuffers = 1;   sbdIn.pBuffers = &sbIn;   sbIn.cbBuffer = cbIn;   sbIn.BufferType = SECBUFFER_TOKEN;   sbIn.pvBuffer = pIn;   ss = _AcceptSecurityContext(&pAS->hcred,         pAS->fInitialized ? &pAS->hctxt : NULL, &sbdIn, 0,         SECURITY_NATIVE_DREP, &pAS->hctxt, &sbdOut, &fContextAttr,         &tsExpiry);   if (ss < 0)  {      fprintf(stderr, "AcceptSecurityContext failed with %08X\n", ss);      return FALSE;   }   pAS->fHaveCtxtHandle = TRUE;   // If necessary, complete token   if (ss == SEC_I_COMPLETE_NEEDED || ss == SEC_I_COMPLETE_AND_CONTINUE) {      if (_CompleteAuthToken) {         ss = _CompleteAuthToken(&pAS->hctxt, &sbdOut);         if (ss < 0)  {            fprintf(stderr, "CompleteAuthToken failed with %08X\n", ss);            return FALSE;         }      }      else {         fprintf (stderr, "CompleteAuthToken not supported.\n");         return FALSE;      }   }   *pcbOut = sbOut.cbBuffer;   if (!pAS->fInitialized)      pAS->fInitialized = TRUE;   *pfDone = !(ss == SEC_I_CONTINUE_NEEDED         || ss == SEC_I_COMPLETE_AND_CONTINUE);   return TRUE;}///////////////////////////////////////////////////////////////////////////////BOOL WINAPI SSPLogonUser(LPTSTR szDomain, LPTSTR szUser, LPTSTR szPassword) {   AUTH_SEQ    asServer   = {0};   AUTH_SEQ    asClient   = {0};   BOOL        fDone      = FALSE;   BOOL        fResult    = FALSE;   DWORD       cbOut      = 0;   DWORD       cbIn       = 0;   DWORD       cbMaxToken = 0;   PVOID       pClientBuf = NULL;   PVOID       pServerBuf = NULL;   PSecPkgInfo pSPI       = NULL;   HMODULE     hModule    = NULL;   SEC_WINNT_AUTH_IDENTITY ai;   __try {      hModule = LoadSecurityDll();      if (!hModule)         __leave;      // Get max token size      _QuerySecurityPackageInfo(_T("NTLM"), &pSPI);      cbMaxToken = pSPI->cbMaxToken;      _FreeContextBuffer(pSPI);      // Allocate buffers for client and server messages      pClientBuf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cbMaxToken);      pServerBuf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cbMaxToken);      // Initialize auth identity structure      ZeroMemory(&ai, sizeof(ai));#if defined(UNICODE) || defined(_UNICODE)      ai.Domain = szDomain;      ai.DomainLength = lstrlen(szDomain);      ai.User = szUser;      ai.UserLength = lstrlen(szUser);      ai.Password = szPassword;      ai.PasswordLength = lstrlen(szPassword);      ai.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;#else      ai.Domain = (unsigned char *)szDomain;      ai.DomainLength = lstrlen(szDomain);      ai.User = (unsigned char *)szUser;      ai.UserLength = lstrlen(szUser);      ai.Password = (unsigned char *)szPassword;      ai.PasswordLength = lstrlen(szPassword);      ai.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI;#endif      // Prepare client message (negotiate) .      cbOut = cbMaxToken;      if (!GenClientContext(&asClient, &ai, NULL, 0, pClientBuf, &cbOut, &fDone))         __leave;      // Prepare server message (challenge) .      cbIn = cbOut;      cbOut = cbMaxToken;      if (!GenServerContext(&asServer, pClientBuf, cbIn, pServerBuf, &cbOut,            &fDone))         __leave;         // Most likely failure: AcceptServerContext fails with SEC_E_LOGON_DENIED         // in the case of bad szUser or szPassword.         // Unexpected Result: Logon will succeed if you pass in a bad szUser and         // the guest account is enabled in the specified domain.      // Prepare client message (authenticate) .      cbIn = cbOut;      cbOut = cbMaxToken;      if (!GenClientContext(&asClient, &ai, pServerBuf, cbIn, pClientBuf, &cbOut,            &fDone))         __leave;      // Prepare server message (authentication) .      cbIn = cbOut;      cbOut = cbMaxToken;      if (!GenServerContext(&asServer, pClientBuf, cbIn, pServerBuf, &cbOut,            &fDone))         __leave;      fResult = TRUE;      {         HANDLE hToken = NULL;         if (_QuerySecurityContextToken(&asServer.hctxt, &hToken) == 0)         {            if (IsGuest(hToken))            {               printf("Logged in as Guest\n");               fResult = FALSE;            }            else               printf("Logged in as the desired user\n");            CloseHandle(hToken);         }      }   } __finally {      // Clean up resources      if (asClient.fHaveCtxtHandle)         _DeleteSecurityContext(&asClient.hctxt);      if (asClient.fHaveCredHandle)         _FreeCredentialsHandle(&asClient.hcred);      if (asServer.fHaveCtxtHandle)         _DeleteSecurityContext(&asServer.hctxt);      if (asServer.fHaveCredHandle)         _FreeCredentialsHandle(&asServer.hcred);      if (hModule)         UnloadSecurityDll(hModule);      HeapFree(GetProcessHeap(), 0, pClientBuf);      HeapFree(GetProcessHeap(), 0, pServerBuf);   }   return fResult;}//--------------------------------------------------------------------// The GetConsoleInput function gets an array of characters from the // keyboard, while printing only asterisks to the screen.void GetConsoleInput(TCHAR* strInput, int intMaxChars){	char ch;	char minChar = ' ';	minChar++;	ch = getch();	while (ch != '\r')	{		if (ch == '\b' && strlen(strInput) > 0)		{			strInput[strlen(strInput)-1]   = '\0';			printf("\b \b");		}		else if (ch >= minChar && (int)strlen(strInput) < intMaxChars)		{			strInput[strlen(strInput)+1] = '\0';			strInput[strlen(strInput)]   = ch;			putch('*');		}		ch = getch();	}	putch('\n');}void _tmain(int argc, TCHAR **argv){	TCHAR password[PWLEN+1];   if (argc != 3) 	{		_tprintf(_T("Usage: %s DomainName UserName\n"), argv[0]);		return;	}	_tprintf(_T("Enter password for the specified user : "));	password[0] = 0;	GetConsoleInput(password, PWLEN);	_tprintf(_T("\n"));   // argv[1] - Domain Name   // argv[2] - User Name   if (SSPLogonUser(argv[1], argv[2], password))   {      _tprintf(_T("User Credentials are valid\n"));   }   else      _tprintf(_T("User Credentials are NOT valid\n"));}
win95 win98 winnt winme win2000 winxp

警告:本文已自动翻译

属性

文章 ID:180548 - 上次审阅时间:10/01/2007 16:35:09 - 修订版本: 4.0

Microsoft Win32 Application Programming Interface

  • kbmt kbapi kbfaq kbhowto kbkernbase kbsecurity KB180548 KbMtzh
反馈