أنت غير متصل حاليًا، وفي انتظار الإنترنت الخاص بك ليقوم بإعادة الاتصال

كيفية التحقق من صحة بيانات اعتماد المستخدم على أنظمة تشغيل

هام: تمت ترجمة هذا المقال باستخدام برنامج ترجمة آلية لشركة مايكروسوفت بدلاً من الاستعانة بمترجم بشري. تقدم شركة مايكروسوفت كلاً من المقالات المترجمة بواسطة المترجمين البشر والمقالات المترجمة آليًا وبالتالي ستتمكن من الوصول إلى كل المقالات الموجودة في قاعدة المعرفة الخاصة بنا وباللغة الخاصة بك. بالرغم من ذلك، فإن المقالة المترجمة آليًا لا تكون دقيقة دائمًا وقد تحتوي على أخطاء إملائية أو لغوية أو نحوية، مثل تلك الأخطاء الصادرة عن متحدث أجنبي عندما يتحدث بلغتك. لا تتحمل شركة مايكروسوفت مسئولية عدم الدقة أو الأخطاء أو الضرر الناتج عن أية أخطاء في ترجمة المحتوى أو استخدامه من قبل عملائنا. تعمل شركة مايكروسوفت باستمرار على ترقية برنامج الترجمة الآلية

اضغط هنا لرابط المقالة باللغة الانجليزية180548
الموجز
من حين لآخر، قد تحتاج تطبيق للتحقق من اسم المستخدم للمستخدم وكلمة المرور (يُشار إليها hereafter بـ بيانات الاعتماد). يمكنك القيام بذلك بطريقتين مختلفة بالاعتماد على نظام التشغيل الذي يتم تشغيل التطبيق.

توضح هذه المقالة كافة الطرق الشائعة للتحقق من بيانات اعتماد المستخدم ومن متطلبات خاصة من أجل كل أسلوب.

ملاحظة تجميع بيانات اعتماد المستخدم من تطبيق وضع مستخدم مزعجة للمستخدمين ويمكن يمكن تقديم فتحة أمان محتملة في بيئة المؤسسة. تمت إضافة متطلبات "تسجيل الدخول الموحدة" (متطلبات أنه يجب أن تتم مطالبة المستخدم فقط كتابة أوراق الاعتماد الخاصة بهم مرة واحدة في الشاشة CTRL + ALT + DEL) ، إلى متطلبات شعار Microsoft BackOffice نظراً لهذه الأسباب جداً. من المهم التأكد من أنك فعلاً تحتاج إلى تجميع بيانات الاعتماد غير مناسب أكثر أساليب أخرى عميل/ملقم التحقق من الصحة. راجع وثائق الأمان في Platform 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 لم يعد المطلوبة أن عملية أن الامتياز SE_TCB_NAME للاتصال LogonUser. لذلك، يكون أبسط أسلوب التحقق من صحة بيانات اعتماد المستخدم في Windows XP، استدعاء API LogonUser.

واحد مشكلة LogonUser غير مطبّق API على نظام التشغيل Windows 95 أو Windows 98 أو Windows Millennium Edition.

يمكنك كخيار آخر استخدام موفر دعم الأمان واجهة (SSPI) القيام بتسجيل دخول نمط شبكة بواسطة توفير بيانات اعتماد المستخدم. يحتوي هذا الأسلوب من عملية التحقق من صحة ميزة لا تتطلب أية الامتياز خاصة كما تعمل على كافة إصدارات Windows. تكون النتيجة النهائي من استخدام خدمات SSPI للتحقق من صحة بيانات الاعتماد لتسجيل دخول يماثل من استدعاء API LogonUser مع نوع تسجيل الدخول LOGON32_LOGON_NETWORK. downside أكبر على هذا النوع من تسجيل الدخول هو أن تتمكن من الوصول البعيد الشبكة موارد بعد انتحال تسجيل دخول نوع شبكة اتصال. إذا كان التطبيق الخاص بك يتصل LogonUser مع نوع تسجيل الدخول LOGON32_LOGON_INTERACTIVE إلى القدرة على NT Windows الحل البديل تنفيذ التفويض ثم SSPI تسجيل الدخول/التحقق من الصحة ربما لن بديلاً viable.

يُظهر نموذج التعليمات البرمجية المتوفرة أدناه كيفية استدعاء خدمات SSPI لتنفيذ تجول بيانات الاعتماد التحقق من الصحة.

لاستخدام هذه الطريقة على Windows 95 وWindows 98 و Windows Millennium Edition لديك أيضاً لتمكين خدمات الأمان NTLM بواسطة فتح لوحة التحكم "و" الشبكة "و" التحكم بالوصول ثم تحديد التحكم بالوصول على مستوى المستخدم.

في Windows XP، يتم تعيين قيمة التسجيل ForceGuest إلى 1 بشكل افتراضي في مفتاح التسجيل التالي:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa
على كمبيوتر يعمل بنظام التشغيل Windows XP الذي عضو في مجموعة عمل:
  • إذا تم تمكين ForceGuest (تعيين إلى 1), SSPI سيتم دوماً محاولة تسجيل الدخول باستخدام حساب المضيف.
  • إذا تم تمكين حساب Guest ستنجح تسجيل دخول SSPI كـ Guest للحصول على أية بيانات اعتماد المستخدم.
  • إذا تم تعطيل الحساب Guest ستفشل تسجيل دخول SSPI حتى بالنسبة بيانات اعتماد صالحة.
  • إذا تم تعطيل ForceGuest (تعيين القيمة إلى 0) ، سيقوم SSPI بتسجيل الدخول باسم المستخدم المحدد.
بالإضافة إلى ذلك، إذا تم تمكين حساب Guest قد تنجح SSPI تسجيل الدخول كـ Guest للحصول على بيانات اعتماد المستخدم غير صالحة. يوضح نموذج C التعليمة البرمجية في هذا المقال كيف يمكنك التحقق من الرمز المميز للوصول سياق الأمان المحددة. تُظهر الدالة المساعد IsGuest في نموذج التعليمة البرمجية كيف يمكنك التحقق من أن حدث تسجيل الدخول كمستخدم المحدد أو كـ Guest.

نموذج التعليمات البرمجية

///////////////////////////////////////////////////////////////////////////////////  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

تحذير: تمت ترجمة هذه المقالة تلقائيًا

خصائص

رقم الموضوع: 180548 - آخر مراجعة: 10/01/2007 16:35:09 - المراجعة: 4.0

Microsoft Win32 واجهة برمجة تطبيقات

  • kbmt kbapi kbfaq kbhowto kbkernbase kbsecurity KB180548 KbMtar
تعليقات
> /html>>c1.microsoft.com/c.gif?DI=4050&did=1&t=">ody>;t=">;did=1&t=">t=">