클라이언트 애플리케이션 만들기
다음 topics Windows 생체 인식 프레임워크 API를 사용하여 프라이빗 센서 풀을 사용하는 클라이언트 애플리케이션을 만드는 방법을 설명합니다.
생체 인식 정보 등록
다음 코드 예제에서는 시스템 풀에 생체 인식 템플릿을 등록하는 방법을 보여 줍니다.
동기 등록
다음 코드 예제:
- WinBioOpenSession을 호출하여 생체 인식 세션을 열고 시스템 풀에 연결합니다.
- WinBioLocateSensor를 호출하여 생체 인식 단위를 찾습니다.
- WinBioEnrollBegin을 호출하여 등록 순서를 시작합니다.
- WinBioEnrollCapture를 호출하여 센서에서 여러 손가락 살짝 밀기를 처리합니다.
- WinBioEnrollCommit을 호출하여 저장소에 템플릿을 저장합니다.
이 샘플을 컴파일하려면 Winbio.lib 정적 라이브러리에 연결하고 다음 헤더 파일을 포함합니다.
- Windows.h
- Stdio.h
- Conio.h
- Winbio.h
HRESULT EnrollSysPool(
BOOL discardEnrollment,
WINBIO_BIOMETRIC_SUBTYPE subFactor)
{
HRESULT hr = S_OK;
WINBIO_IDENTITY identity = {0};
WINBIO_SESSION_HANDLE sessionHandle = NULL;
WINBIO_UNIT_ID unitId = 0;
WINBIO_REJECT_DETAIL rejectDetail = 0;
BOOLEAN isNewTemplate = TRUE;
// Connect to the system pool.
hr = WinBioOpenSession(
WINBIO_TYPE_FINGERPRINT, // Service provider
WINBIO_POOL_SYSTEM, // Pool type
WINBIO_FLAG_DEFAULT, // Configuration and access
NULL, // Array of biometric unit IDs
0, // Count of biometric unit IDs
NULL, // Database ID
&sessionHandle // [out] Session handle
);
if (FAILED(hr))
{
wprintf_s(L"\n WinBioOpenSession failed. ");
wprintf_s(L"hr = 0x%x\n", hr);
goto e_Exit;
}
// Locate a sensor.
wprintf_s(L"\n Swipe your finger on the sensor...\n");
hr = WinBioLocateSensor( sessionHandle, &unitId);
if (FAILED(hr))
{
wprintf_s(L"\n WinBioLocateSensor failed. hr = 0x%x\n", hr);
goto e_Exit;
}
// Begin the enrollment sequence.
wprintf_s(L"\n Starting enrollment sequence...\n");
hr = WinBioEnrollBegin(
sessionHandle, // Handle to open biometric session
subFactor, // Finger to create template for
unitId // Biometric unit ID
);
if (FAILED(hr))
{
wprintf_s(L"\n WinBioEnrollBegin failed. hr = 0x%x\n", hr);
goto e_Exit;
}
// Capture enrollment information by swiping the sensor with
// the finger identified by the subFactor argument in the
// WinBioEnrollBegin function.
for (int swipeCount = 1;; ++swipeCount)
{
wprintf_s(L"\n Swipe the sensor to capture %s sample.",
(swipeCount == 1)?L"the first":L"another");
hr = WinBioEnrollCapture(
sessionHandle, // Handle to open biometric session
&rejectDetail // [out] Failure information
);
wprintf_s(L"\n Sample %d captured from unit number %d.",
swipeCount,
unitId);
if (hr == WINBIO_I_MORE_DATA)
{
wprintf_s(L"\n More data required.\n");
continue;
}
if (FAILED(hr))
{
if (hr == WINBIO_E_BAD_CAPTURE)
{
wprintf_s(L"\n Error: Bad capture; reason: %d",
rejectDetail);
continue;
}
else
{
wprintf_s(L"\n WinBioEnrollCapture failed. hr = 0x%x", hr);
goto e_Exit;
}
}
else
{
wprintf_s(L"\n Template completed.\n");
break;
}
}
// Discard the enrollment if the appropriate flag is set.
// Commit the enrollment if it is not discarded.
if (discardEnrollment == TRUE)
{
wprintf_s(L"\n Discarding enrollment...\n\n");
hr = WinBioEnrollDiscard( sessionHandle );
if (FAILED(hr))
{
wprintf_s(L"\n WinBioLocateSensor failed. hr = 0x%x\n", hr);
}
goto e_Exit;
}
else
{
wprintf_s(L"\n Committing enrollment...\n");
hr = WinBioEnrollCommit(
sessionHandle, // Handle to open biometric session
&identity, // WINBIO_IDENTITY object for the user
&isNewTemplate); // Is this a new template
if (FAILED(hr))
{
wprintf_s(L"\n WinBioEnrollCommit failed. hr = 0x%x\n", hr);
goto e_Exit;
}
}
e_Exit:
if (sessionHandle != NULL)
{
WinBioCloseSession(sessionHandle);
sessionHandle = NULL;
}
wprintf_s(L" Press any key to continue...");
_getch();
return hr;
}
비동기 등록
다음 코드 예제:
- WinBioOpenSession을 호출하여 생체 인식 세션을 열고 시스템 풀에 연결합니다.
- WinBioLocateSensor를 호출하여 생체 인식 단위를 찾습니다.
- WinBioEnrollBegin을 호출하여 등록 순서를 시작합니다.
- WinBioEnrollCaptureWithCallback을 호출하여 여러 손가락 살짝 밀기를 처리합니다. 이 함수는 비동기이며 사용자 지정 콜백 함수를 사용하여 별도의 스레드에서 처리를 계속합니다. 예제 콜백 함수는 아래에 포함되어 있습니다.
- WinBioWait을 호출하여 비동기 등록 프로세스가 완료되거나 취소될 때까지 기다립니다.
- WinBioEnrollCommit을 호출하여 템플릿을 저장합니다.
Winbio.lib 정적 라이브러리에 연결하여 이 샘플을 컴파일합니다.
//------------------------------------------------------------------------
// EnrollSystemPoolWithCallback.cpp : Entry point for the application.
//
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <winbio.h>
//------------------------------------------------------------------------
// Forward declarations.
//
HRESULT EnrollSysPoolWithCallback(
BOOL bCancel,
BOOL bDiscard,
WINBIO_BIOMETRIC_SUBTYPE subFactor);
VOID CALLBACK EnrollCaptureCallback(
__in_opt PVOID EnrollCallbackContext,
__in HRESULT OperationStatus,
__in WINBIO_REJECT_DETAIL RejectDetail);
typedef struct _ENROLL_CALLBACK_CONTEXT {
WINBIO_SESSION_HANDLE SessionHandle;
WINBIO_UNIT_ID UnitId;
WINBIO_BIOMETRIC_SUBTYPE SubFactor;
} ENROLL_CALLBACK_CONTEXT, *PENROLL_CALLBACK_CONTEXT;
//------------------------------------------------------------------------
int wmain()
{
HRESULT hr = S_OK;
hr = EnrollSysPoolWithCallback(
FALSE,
FALSE,
WINBIO_ANSI_381_POS_RH_INDEX_FINGER);
return 0;
}
//------------------------------------------------------------------------
// The following function enrolls a user's fingerprint in the system pool.
// The function calls WinBioEnrollCaptureWithCallback and waits for the
// asynchronous enrollment process to be completed or canceled.
//
HRESULT EnrollSysPoolWithCallback(
BOOL bCancel,
BOOL bDiscard,
WINBIO_BIOMETRIC_SUBTYPE subFactor)
{
// Declare variables
HRESULT hr = S_OK;
WINBIO_IDENTITY identity = {0};
WINBIO_SESSION_HANDLE sessionHandle = NULL;
WINBIO_UNIT_ID unitId = 0;
BOOLEAN isNewTemplate = TRUE;
ENROLL_CALLBACK_CONTEXT callbackContext = {0};
// Connect to the system pool.
hr = WinBioOpenSession(
WINBIO_TYPE_FINGERPRINT, // Service provider
WINBIO_POOL_SYSTEM, // Pool type
WINBIO_FLAG_DEFAULT, // Configuration and access
NULL, // Array of biometric unit IDs
0, // Count of biometric unit IDs
NULL, // Database ID
&sessionHandle // [out] Session handle
);
if (FAILED(hr))
{
wprintf_s(L"\n WinBioEnumBiometricUnits failed. ");
wprintf_s(L"hr = 0x%x\n", hr);
goto e_Exit;
}
// Locate the sensor.
wprintf_s(L"\n Swipe your finger to locate the sensor...\n");
hr = WinBioLocateSensor( sessionHandle, &unitId);
if (FAILED(hr))
{
wprintf_s(L"\n WinBioLocateSensor failed. hr = 0x%x\n", hr);
goto e_Exit;
}
// Begin the enrollment sequence.
hr = WinBioEnrollBegin(
sessionHandle, // Handle to open biometric session
subFactor, // Finger to create template for
unitId // Biometric unit ID
);
if (FAILED(hr))
{
wprintf_s(L"\n WinBioEnrollBegin failed. hr = 0x%x\n", hr);
goto e_Exit;
}
// Set up the custom callback context structure.
callbackContext.SessionHandle = sessionHandle;
callbackContext.UnitId = unitId;
callbackContext.SubFactor = subFactor;
// Call WinBioEnrollCaptureWithCallback. This is an asynchronous
// method that returns immediately.
hr = WinBioEnrollCaptureWithCallback(
sessionHandle, // Handle to open biometric session
EnrollCaptureCallback, // Callback function
&callbackContext // Pointer to the custom context
);
if (FAILED(hr))
{
wprintf_s(L"\n WinBioEnrollCaptureWithCallback failed. ");
wprintf_s(L"hr = 0x%x\n", hr);
goto e_Exit;
}
wprintf_s(L"\n Swipe the sensor with the appropriate finger...\n");
// Cancel the enrollment if the bCancel flag is set.
if (bCancel)
{
wprintf_s(L"\n Starting CANCEL timer...\n");
Sleep( 7000 );
wprintf_s(L"\n Calling WinBioCancel\n");
hr = WinBioCancel( sessionHandle );
if (FAILED(hr))
{
wprintf_s(L"\n WinBioCancel failed. hr = 0x%x\n", hr);
goto e_Exit;
}
}
// Wait for the asynchronous enrollment process to complete
// or be canceled.
hr = WinBioWait( sessionHandle );
if (FAILED(hr))
{
wprintf_s(L"\n WinBioWait failed. hr = 0x%x\n", hr);
}
// Discard the enrollment if the bDiscard flag is set.
// Commit the enrollment if the flag is not set.
if (bDiscard)
{
wprintf_s(L"\n Discarding enrollment...\n");
hr = WinBioEnrollDiscard( sessionHandle );
if (FAILED(hr))
{
wprintf_s(L"\n WinBioLocateSensor failed. ");
wprintf_s(L"hr = 0x%x\n", hr);
}
goto e_Exit;
}
else
{
wprintf_s(L"\n Committing enrollment...\n");
hr = WinBioEnrollCommit(
sessionHandle, // Handle to open biometric session
&identity, // WINBIO_IDENTITY object for the user
&isNewTemplate); // Is this a new template
if (FAILED(hr))
{
wprintf_s(L"\n WinBioEnrollCommit failed. hr = 0x%x\n", hr);
goto e_Exit;
}
}
e_Exit:
if (sessionHandle != NULL)
{
WinBioCloseSession(sessionHandle);
sessionHandle = NULL;
}
wprintf_s(L"\n Press any key to exit...");
_getch();
return hr;
}
//------------------------------------------------------------------------
// The following function is the callback for the Windows Biometric
// Framework WinBioEnrollCaptureWithCallback() function.
//
VOID CALLBACK EnrollCaptureCallback(
__in_opt PVOID EnrollCallbackContext,
__in HRESULT OperationStatus,
__in WINBIO_REJECT_DETAIL RejectDetail
)
{
// Declare variables.
HRESULT hr = S_OK;
static SIZE_T swipeCount = 1;
PENROLL_CALLBACK_CONTEXT callbackContext =
(PENROLL_CALLBACK_CONTEXT)EnrollCallbackContext;
wprintf_s(L"\n EnrollCaptureCallback executing\n");
wprintf_s(L"\n Sample %d captured", swipeCount++);
// The capture was not acceptable or the enrollment operation
// failed.
if (FAILED(OperationStatus))
{
if (OperationStatus == WINBIO_E_BAD_CAPTURE)
{
wprintf_s(L"\n Bad capture; reason: %d\n", RejectDetail);
wprintf_s(L"\n Swipe your finger to capture another sample.\n");
// Try again.
hr = WinBioEnrollCaptureWithCallback(
callbackContext->SessionHandle, // Open session handle
EnrollCaptureCallback, // Callback function
EnrollCallbackContext // Callback context
);
if (FAILED(hr))
{
wprintf_s(L"WinBioEnrollCaptureWithCallback failed.");
wprintf_s(L"hr = 0x%x\n", hr);
}
}
else
{
wprintf_s(L"EnrollCaptureCallback failed.");
wprintf_s(L"OperationStatus = 0x%x\n", OperationStatus);
}
goto e_Exit;
}
// The enrollment operation requires more fingerprint swipes.
// This is normal and depends on your hardware. Typically, at least
// three swipes are required.
if (OperationStatus == WINBIO_I_MORE_DATA)
{
wprintf_s(L"\n More data required.");
wprintf_s(L"\n Swipe your finger on the sensor again.");
hr = WinBioEnrollCaptureWithCallback(
callbackContext->SessionHandle,
EnrollCaptureCallback,
EnrollCallbackContext
);
if (FAILED(hr))
{
wprintf_s(L"WinBioEnrollCaptureWithCallback failed. ");
wprintf_s(L"hr = 0x%x\n", hr);
}
goto e_Exit;
}
wprintf_s(L"\n Template completed\n");
e_Exit:
return;
}
생체 인식 단위 찾기
다음 코드 예제에서는 설치된 생체 인식 단위를 찾는 방법을 보여 줍니다.
동기적으로 생체 인식 단위 찾기
다음 코드 예제:
- WinBioOpenSession을 호출하여 생체 인식 세션을 열고 시스템 풀에 연결합니다.
- WinBioLocateSensor를 호출하여 생체 인식 단위를 찾습니다.
이 샘플을 컴파일하려면 Winbio.lib 정적 라이브러리에 연결하고 다음 헤더 파일을 포함합니다.
- Windows.h
- Stdio.h
- Conio.h
- Winbio.h
HRESULT LocateSensor( )
{
HRESULT hr = S_OK;
WINBIO_SESSION_HANDLE sessionHandle = NULL;
WINBIO_UNIT_ID unitId = 0;
// Connect to the system pool.
hr = WinBioOpenSession(
WINBIO_TYPE_FINGERPRINT, // Service provider
WINBIO_POOL_SYSTEM, // Pool type
WINBIO_FLAG_DEFAULT, // Configuration and access
NULL, // Array of biometric unit IDs
0, // Count of biometric unit IDs
NULL, // Database ID
&sessionHandle // [out] Session handle
);
if (FAILED(hr))
{
wprintf_s(L"\n WinBioEnumBiometricUnits failed. hr = 0x%x\n", hr);
goto e_Exit;
}
// Locate the sensor.
wprintf_s(L"\n Tap the sensor once...\n");
hr = WinBioLocateSensor( sessionHandle, &unitId);
if (FAILED(hr))
{
wprintf_s(L"\n WinBioLocateSensor failed. hr = 0x%x\n", hr);
goto e_Exit;
}
wprintf_s(L"\n Sensor located successfully. ");
wprintf_s(L"\n Unit ID = %d \n", unitId);
e_Exit:
if (sessionHandle != NULL)
{
WinBioCloseSession(sessionHandle);
sessionHandle = NULL;
}
wprintf_s(L"\n Hit any key to exit...");
_getch();
return hr;
}
비동기적으로 생체 인식 단위 찾기
다음 코드 예제:
- WinBioOpenSession을 호출하여 생체 인식 세션을 열고 시스템 풀에 연결합니다.
- WinBioLocateSensorWithCallback을 호출하여 생체 인식 센서를 찾습니다. 다른 스레드에서 센서를 찾도록 생체 인식 하위 시스템을 구성하는 비동기 함수입니다. 생체 인식 하위 시스템의 출력은 여기에서 LocateSensorCallback이라는 사용자 지정 콜백 함수로 전송됩니다.
- WinBioWait을 호출하여 비동기 프로세스가 완료되거나 취소될 때까지 기다립니다.
이 샘플을 컴파일하려면 Winbio.lib 정적 라이브러리에 연결하고 다음 헤더 파일을 포함합니다.
- Windows.h
- Stdio.h
- Conio.h
- Winbio.h
HRESULT LocateSensorWithCallback(BOOL bCancel)
{
HRESULT hr = S_OK;
WINBIO_SESSION_HANDLE sessionHandle = NULL;
WINBIO_UNIT_ID unitId = 0;
// Connect to the system pool.
hr = WinBioOpenSession(
WINBIO_TYPE_FINGERPRINT, // Service provider
WINBIO_POOL_SYSTEM, // Pool type
WINBIO_FLAG_DEFAULT, // Configuration and access
NULL, // Array of biometric unit IDs
0, // Count of biometric unit IDs
NULL, // Database ID
&sessionHandle // [out] Session handle
);
if (FAILED(hr))
{
wprintf_s(L"\n WinBioOpenSession failed. hr = 0x%x\n", hr);
goto e_Exit;
}
wprintf_s(L"\n Calling WinBioLocateSensorWithCallback.");
hr = WinBioLocateSensorWithCallback(
sessionHandle, // Open biometric session
LocateSensorCallback, // Callback function
NULL // Optional context
);
if (FAILED(hr))
{
wprintf_s(L"\n WinBioLocateSensorWithCallback failed.");
wprintf_s(L"hr = 0x%x\n", hr);
goto e_Exit;
}
wprintf_s(L"\n Swipe the sensor ...\n");
// Cancel the identification if the bCancel flag is set.
if (bCancel)
{
wprintf_s(L"\n Starting CANCEL timer...\n");
Sleep( 7000 );
wprintf_s(L"\n Calling WinBioCancel\n");
hr = WinBioCancel( sessionHandle );
if (FAILED(hr))
{
wprintf_s(L"\n WinBioCancel failed. hr = 0x%x\n", hr);
goto e_Exit;
}
}
// Wait for the asynchronous identification process to complete
// or be canceled.
hr = WinBioWait( sessionHandle );
if (FAILED(hr))
{
wprintf_s(L"\n WinBioWait failed. hr = 0x%x\n", hr);
}
e_Exit:
if (sessionHandle != NULL)
{
wprintf_s(L"\n Closing the session.\n");
hr = WinBioCloseSession(sessionHandle);
if (FAILED(hr))
{
wprintf_s(L"\n WinBioCloseSession failed. hr = 0x%x\n", hr);
}
sessionHandle = NULL;
}
wprintf_s(L"\n Hit any key to exit...");
_getch();
return hr;
}
//------------------------------------------------------------------------
// The following function is the callback for
// WinBioLocateSensorWithCallback. The function filters the response
// from the biometric subsystem and writes a result to the console window.
//
VOID CALLBACK LocateSensorCallback(
__in_opt PVOID LocateCallbackContext,
__in HRESULT OperationStatus,
__in WINBIO_UNIT_ID UnitId
)
{
UNREFERENCED_PARAMETER(LocateCallbackContext);
wprintf_s(L"\n LocateSensorCallback executing.");
// A sensor could not be located.
if (FAILED(OperationStatus))
{
wprintf_s(L"\n LocateSensorCallback failed.");
wprintf_s(L"OperationStatus = 0x%x\n", OperationStatus);
}
// A sensor was located.
else
{
wprintf_s(L"\n Selected unit ID: %d\n", UnitId);
}
}
사용자 ID 확인
동기 확인
다음 코드 예제:
- WinBioOpenSession을 호출하여 생체 인식 세션을 열고 시스템 풀에 연결합니다.
- WinBioVerify를 호출하여 생체 인식 샘플이 현재 사용자의 로그온 ID와 일치하는지 여부를 확인합니다.
이 샘플을 컴파일하려면 Winbio.lib 정적 라이브러리에 연결하고 다음 헤더 파일을 포함합니다.
- Windows.h
- Stdio.h
- Conio.h
- Winbio.h
HRESULT Verify(WINBIO_BIOMETRIC_SUBTYPE subFactor)
{
HRESULT hr = S_OK;
WINBIO_SESSION_HANDLE sessionHandle = NULL;
WINBIO_UNIT_ID unitId = 0;
WINBIO_REJECT_DETAIL rejectDetail = 0;
WINBIO_IDENTITY identity = {0};
BOOLEAN match = FALSE;
// Find the identity of the user.
hr = GetCurrentUserIdentity( &identity );
if (FAILED(hr))
{
wprintf_s(L"\n User identity not found. hr = 0x%x\n", hr);
goto e_Exit;
}
// Connect to the system pool.
hr = WinBioOpenSession(
WINBIO_TYPE_FINGERPRINT, // Service provider
WINBIO_POOL_SYSTEM, // Pool type
WINBIO_FLAG_DEFAULT, // Configuration and access
NULL, // Array of biometric unit IDs
0, // Count of biometric unit IDs
NULL, // Database ID
&sessionHandle // [out] Session handle
);
if (FAILED(hr))
{
wprintf_s(L"\n WinBioOpenSession failed. hr = 0x%x\n", hr);
goto e_Exit;
}
// Verify a biometric sample.
wprintf_s(L"\n Calling WinBioVerify - Swipe finger on sensor...\n");
hr = WinBioVerify(
sessionHandle,
&identity,
subFactor,
&unitId,
&match,
&rejectDetail
);
wprintf_s(L"\n Swipe processed - Unit ID: %d\n", unitId);
if (FAILED(hr))
{
if (hr == WINBIO_E_NO_MATCH)
{
wprintf_s(L"\n- NO MATCH - identity verification failed.\n");
}
else if (hr == WINBIO_E_BAD_CAPTURE)
{
wprintf_s(L"\n- Bad capture; reason: %d\n", rejectDetail);
}
else
{
wprintf_s(L"\n WinBioVerify failed. hr = 0x%x\n", hr);
}
goto e_Exit;
}
wprintf_s(L"\n Fingerprint verified:\n", unitId);
e_Exit:
if (sessionHandle != NULL)
{
WinBioCloseSession(sessionHandle);
sessionHandle = NULL;
}
wprintf_s(L"\n Press any key to exit...");
_getch();
return hr;
}
//------------------------------------------------------------------------
// The following function retrieves the identity of the current user.
// This is a helper function and is not part of the Windows Biometric
// Framework API.
//
HRESULT GetCurrentUserIdentity(__inout PWINBIO_IDENTITY Identity)
{
// Declare variables.
HRESULT hr = S_OK;
HANDLE tokenHandle = NULL;
DWORD bytesReturned = 0;
struct{
TOKEN_USER tokenUser;
BYTE buffer[SECURITY_MAX_SID_SIZE];
} tokenInfoBuffer;
// Zero the input identity and specify the type.
ZeroMemory( Identity, sizeof(WINBIO_IDENTITY));
Identity->Type = WINBIO_ID_TYPE_NULL;
// Open the access token associated with the
// current process
if (!OpenProcessToken(
GetCurrentProcess(), // Process handle
TOKEN_READ, // Read access only
&tokenHandle)) // Access token handle
{
DWORD win32Status = GetLastError();
wprintf_s(L"Cannot open token handle: %d\n", win32Status);
hr = HRESULT_FROM_WIN32(win32Status);
goto e_Exit;
}
// Zero the tokenInfoBuffer structure.
ZeroMemory(&tokenInfoBuffer, sizeof(tokenInfoBuffer));
// Retrieve information about the access token. In this case,
// retrieve a SID.
if (!GetTokenInformation(
tokenHandle, // Access token handle
TokenUser, // User for the token
&tokenInfoBuffer.tokenUser, // Buffer to fill
sizeof(tokenInfoBuffer), // Size of the buffer
&bytesReturned)) // Size needed
{
DWORD win32Status = GetLastError();
wprintf_s(L"Cannot query token information: %d\n", win32Status);
hr = HRESULT_FROM_WIN32(win32Status);
goto e_Exit;
}
// Copy the SID from the tokenInfoBuffer structure to the
// WINBIO_IDENTITY structure.
CopySid(
SECURITY_MAX_SID_SIZE,
Identity->Value.AccountSid.Data,
tokenInfoBuffer.tokenUser.User.Sid
);
// Specify the size of the SID and assign WINBIO_ID_TYPE_SID
// to the type member of the WINBIO_IDENTITY structure.
Identity->Value.AccountSid.Size = GetLengthSid(tokenInfoBuffer.tokenUser.User.Sid);
Identity->Type = WINBIO_ID_TYPE_SID;
e_Exit:
if (tokenHandle != NULL)
{
CloseHandle(tokenHandle);
}
return hr;
}
비동기 확인
다음 코드 예제:
- WinBioOpenSession을 호출하여 생체 인식 세션을 열고 시스템 풀에 연결합니다.
- WinBioVerifyWithCallback을 호출하여 생체 인식 샘플이 현재 사용자의 로그온 ID와 일치하는지 여부를 확인합니다. 다른 스레드에서 사용자를 확인하도록 생체 인식 하위 시스템을 구성하는 비동기 함수입니다. 생체 인식 하위 시스템의 출력은 VerifyCallback이라는 사용자 지정 콜백 함수로 전송됩니다.
- WinBioWait을 호출하여 비동기 프로세스가 완료되거나 취소될 때까지 기다립니다.
이 샘플을 컴파일하려면 Winbio.lib 정적 라이브러리에 연결하고 다음 헤더 파일을 포함합니다.
- Windows.h
- Stdio.h
- Conio.h
- Winbio.h
HRESULT VerifyWithCallback(BOOL bCancel, WINBIO_BIOMETRIC_SUBTYPE subFactor)
{
// Declare variables.
HRESULT hr = S_OK;
WINBIO_SESSION_HANDLE sessionHandle = NULL;
WINBIO_UNIT_ID unitId = 0;
WINBIO_REJECT_DETAIL rejectDetail = 0;
WINBIO_IDENTITY identity = {0};
// Find the identity of the user.
hr = GetCurrentUserIdentity( &identity );
if (FAILED(hr))
{
wprintf_s(L"\n User identity not found. hr = 0x%x\n", hr);
goto e_Exit;
}
// Connect to the system pool.
hr = WinBioOpenSession(
WINBIO_TYPE_FINGERPRINT, // Service provider
WINBIO_POOL_SYSTEM, // Pool type
WINBIO_FLAG_DEFAULT, // Configuration and access
NULL, // Array of biometric unit IDs
0, // Count of biometric unit IDs
NULL, // Database ID
&sessionHandle // [out] Session handle
);
if (FAILED(hr))
{
wprintf_s(L"\n WinBioOpenSession failed. hr = 0x%x\n", hr);
goto e_Exit;
}
// Verify a biometric sample asynchronously.
wprintf_s(L"\n Calling WinBioVerifyWithCallback.\n");
hr = WinBioVerifyWithCallback(
sessionHandle, // Open session handle
&identity, // User SID or GUID
subFactor, // Sample sub-factor
VerifyCallback, // Callback function
NULL // Optional context
);
if (FAILED(hr))
{
wprintf_s(L"\n WinBioVerifyWithCallback failed. hr = 0x%x\n", hr);
goto e_Exit;
}
wprintf_s(L"\n Swipe the sensor ...\n");
// Cancel the identification if the bCancel flag is set.
if (bCancel)
{
wprintf_s(L"\n Starting CANCEL timer...\n");
Sleep( 7000 );
wprintf_s(L"\n Calling WinBioCancel\n");
hr = WinBioCancel( sessionHandle );
if (FAILED(hr))
{
wprintf_s(L"\n WinBioCancel failed. hr = 0x%x\n", hr);
goto e_Exit;
}
}
// Wait for the asynchronous identification process to complete
// or be canceled.
hr = WinBioWait( sessionHandle );
if (FAILED(hr))
{
wprintf_s(L"\n WinBioWait failed. hr = 0x%x\n", hr);
}
e_Exit:
if (sessionHandle != NULL)
{
WinBioCloseSession(sessionHandle);
sessionHandle = NULL;
}
wprintf_s(L"\n Hit any key to continue...");
_getch();
return hr;
}
//------------------------------------------------------------------------
// The following function is the callback for WinBioVerifyWithCallback.
// The function filters the response from the biometric subsystem and
// writes a result to the console window.
//
VOID CALLBACK VerifyCallback(
__in_opt PVOID VerifyCallbackContext,
__in HRESULT OperationStatus,
__in WINBIO_UNIT_ID UnitId,
__in BOOLEAN Match,
__in WINBIO_REJECT_DETAIL RejectDetail
)
{
UNREFERENCED_PARAMETER(VerifyCallbackContext);
UNREFERENCED_PARAMETER(Match);
wprintf_s(L"\n VerifyCallback executing");
wprintf_s(L"\n Swipe processed for unit ID %d\n", UnitId);
// The identity could not be verified.
if (FAILED(OperationStatus))
{
wprintf_s(L"\n Verification failed for the following reason:");
if (OperationStatus == WINBIO_E_NO_MATCH)
{
wprintf_s(L"\n No match.\n");
}
else if (OperationStatus == WINBIO_E_BAD_CAPTURE)
{
wprintf_s(L"\n Bad capture.\n ");
wprintf_s(L"\n Bad capture; reason: %d\n", RejectDetail);
}
else
{
wprintf_s(L"VerifyCallback failed.");
wprintf_s(L"OperationStatus = 0x%x\n", OperationStatus);
}
goto e_Exit;
}
// The user identity was verified.
wprintf_s(L"\n Fingerprint verified:\n");
e_Exit:
return;
}
//------------------------------------------------------------------------
// The following function retrieves the identity of the current user.
// This is a helper function and is not part of the Windows Biometric
// Framework API.
//
HRESULT GetCurrentUserIdentity(__inout PWINBIO_IDENTITY Identity)
{
// Declare variables.
HRESULT hr = S_OK;
HANDLE tokenHandle = NULL;
DWORD bytesReturned = 0;
struct{
TOKEN_USER tokenUser;
BYTE buffer[SECURITY_MAX_SID_SIZE];
} tokenInfoBuffer;
// Zero the input identity and specify the type.
ZeroMemory( Identity, sizeof(WINBIO_IDENTITY));
Identity->Type = WINBIO_ID_TYPE_NULL;
// Open the access token associated with the
// current process
if (!OpenProcessToken(
GetCurrentProcess(), // Process handle
TOKEN_READ, // Read access only
&tokenHandle)) // Access token handle
{
DWORD win32Status = GetLastError();
wprintf_s(L"Cannot open token handle: %d\n", win32Status);
hr = HRESULT_FROM_WIN32(win32Status);
goto e_Exit;
}
// Zero the tokenInfoBuffer structure.
ZeroMemory(&tokenInfoBuffer, sizeof(tokenInfoBuffer));
// Retrieve information about the access token. In this case,
// retrieve a SID.
if (!GetTokenInformation(
tokenHandle, // Access token handle
TokenUser, // User for the token
&tokenInfoBuffer.tokenUser, // Buffer to fill
sizeof(tokenInfoBuffer), // Size of the buffer
&bytesReturned)) // Size needed
{
DWORD win32Status = GetLastError();
wprintf_s(L"Cannot query token information: %d\n", win32Status);
hr = HRESULT_FROM_WIN32(win32Status);
goto e_Exit;
}
// Copy the SID from the tokenInfoBuffer structure to the
// WINBIO_IDENTITY structure.
CopySid(
SECURITY_MAX_SID_SIZE,
Identity->Value.AccountSid.Data,
tokenInfoBuffer.tokenUser.User.Sid
);
// Specify the size of the SID and assign WINBIO_ID_TYPE_SID
// to the type member of the WINBIO_IDENTITY structure.
Identity->Value.AccountSid.Size = GetLengthSid(tokenInfoBuffer.tokenUser.User.Sid);
Identity->Type = WINBIO_ID_TYPE_SID;
e_Exit:
if (tokenHandle != NULL)
{
CloseHandle(tokenHandle);
}
return hr;
}
자격 증명 관리
자격 증명 공급자와 자격 증명 관리자는 Windows 생체 인식 프레임워크의 구성 요소입니다. 공급자는 보안 저장소에서 사용자 자격 증명을 검색하고 로그온, 잠금 해제, 암호 변경 및 UAC 권한 상승 요청에 응답합니다. 또한 빠른 사용자 전환 중에 응답하여 새 사용자를 로그온합니다. 관리자는 로그온 자격 증명을 생체 인식 ID에 매핑하고 자격 증명을 안전하게 저장합니다. 매핑은 일반적으로 생체 인식 등록 중에 타사 등록 애플리케이션에 의해 생성되지만 등록된 사용자가 생체 인식 인증을 시도하지만 등록되지 않았거나 자격 증명이 보안 저장소의 자격 증명과 일치하지 않는 경우 로그온하는 동안 Windows 생체 인식 자격 증명 공급자가 만들 수도 있습니다.
자격 증명 관리자 API 지침
- 게스트 또는 기본 제공 관리자 계정 또는 LocalSystem, LocalService 또는 NetworkService와 같은 비대화형 계정에 대한 자격 증명을 저장, 쿼리 또는 삭제할 수 없습니다.
- 모든 함수는 E_ACCESSDENIED 같은 일반적인 오류 코드이거나 WINBIO_E_UNKNOWN_ID 같은 자격 증명 관리자와 관련된 오류일 수 있는 HRESULT 오류 코드를 반환합니다.
- 적절한 경우 SEC_E_LOGON_DENIED 또는 WINBIO_E_UNKNOWN_ID 같은 보다 구체적인 오류 코드가 반환되기 전에 E_ACCESSDENIED 반환됩니다.
- 권한이 상승되지 않은 사용자는 자신의 계정에 대해서만 자격 증명을 설정, 쿼리 또는 제거할 수 있습니다. 관리자 권한 호출자는 자격 증명 상태를 쿼리하고 다른 사용자의 자격 증명을 제거할 수 있습니다.
- 모든 함수가 실패하고 WINBIO_E_CRED_PROV_DISABLED 반환합니다.
- 자격 증명 공급자가 시스템 전체에서 사용하도록 설정되지 않은 경우 모든 사용자에 대해
- 도메인 사용자에 대 한 공급자를 사용 하도록 설정 되지 않은 경우 도메인 사용 합니다.
- 자격 증명을 추가하거나 제거할 때 이벤트 알림이 생성됩니다.
자격 증명 설정
다음 코드 예제:
- GetCurrentUserIdentity를 호출하여 현재 사용자의 WINBIO_IDENTITY 개체를 검색합니다. GetCurrentUserIdentity는 도우미 함수이며 Windows 생체 인식 프레임워크의 일부가 아닙니다.
- GetCredentials 도우미 함수를 호출하여 인증 정보가 포함된 바이트 배열을 검색합니다. GetCredentials는 사용자에게 자격 증명을 묻는 대화 상자를 표시합니다.
- WinBioSetCredential을 호출하여 저장소에 자격 증명을 저장합니다.
Winbio.lib 정적 라이브러리에 대한 이 함수 링크를 컴파일하고 다음 헤더 파일을 포함하려면 다음을 수행합니다.
- Windows.h
- Wincred.h
- Stdio.h
- Conio.h
- Winbio.h
HRESULT SetCredential()
{
// Declare variables.
HRESULT hr = S_OK;
ULONG ulAuthPackage = 0;
PVOID pvAuthBlob = NULL;
ULONG cbAuthBlob = 0;
WINBIO_IDENTITY identity;
PSID pSid = NULL;
// Find the identity of the user.
wprintf_s(L"\n Finding user identity.\n");
hr = GetCurrentUserIdentity( &identity );
if (FAILED(hr))
{
wprintf_s(L"\n User identity not found. hr = 0x%x\n", hr);
return hr;
}
// Set a pointer to the security descriptor for the user.
pSid = identity.Value.AccountSid.Data;
// Retrieve a byte array that contains credential information.
hr = GetCredentials(pSid, &pvAuthBlob, &cbAuthBlob);
if (FAILED(hr))
{
wprintf_s(L"\n GetCredentials failed. hr = 0x%x\n", hr);
goto e_Exit;
}
// Set the credentials.
hr = WinBioSetCredential(
WINBIO_CREDENTIAL_PASSWORD, // Type of credential.
(PUCHAR)pvAuthBlob, // Credentials byte array
cbAuthBlob, // Size of credentials
WINBIO_PASSWORD_PACKED); // Credentials format
if (FAILED(hr))
{
wprintf_s(L"\n WinBioSetCredential failed. hr = 0x%x\n", hr);
goto e_Exit;
}
wprintf_s(L"\n Credentials successfully set.\n");
e_Exit:
// Delete the authentication byte array.
if (NULL != pvAuthBlob)
{
SecureZeroMemory(pvAuthBlob, cbAuthBlob);
CoTaskMemFree(pvAuthBlob);
pvAuthBlob = NULL;
}
wprintf_s(L"\n Press any key to exit...");
_getch();
return hr;
}
//------------------------------------------------------------------------
// The following function displays a dialog box to prompt a user
// for credentials.
//
HRESULT GetCredentials(PSID pSid, PVOID* ppvAuthBlob, ULONG* pcbAuthBlob)
{
HRESULT hr = S_OK;
DWORD dwResult;
WCHAR szUsername[MAX_PATH] = {0};
DWORD cchUsername = ARRAYSIZE(szUsername);
WCHAR szPassword[MAX_PATH] = {0};
WCHAR szDomain[MAX_PATH] = {0};
DWORD cchDomain = ARRAYSIZE(szDomain);
WCHAR szDomainAndUser[MAX_PATH] = {0};
DWORD cchDomainAndUser = ARRAYSIZE(szDomainAndUser);
PVOID pvInAuthBlob = NULL;
ULONG cbInAuthBlob = 0;
PVOID pvAuthBlob = NULL;
ULONG cbAuthBlob = 0;
CREDUI_INFOW ui;
ULONG ulAuthPackage = 0;
BOOL fSave = FALSE;
static const WCHAR WINBIO_CREDPROV_TEST_PASSWORD_PROMPT_MESSAGE[] =
L"Enter your current password to enable biometric logon.";
static const WCHAR WINBIO_CREDPROV_TEST_PASSWORD_PROMPT_CAPTION[] =
L"Biometric Log On Enrollment";
if (NULL == pSid || NULL == ppvAuthBlob || NULL == pcbAuthBlob)
{
return E_INVALIDARG;
}
// Retrieve the user name and domain name.
SID_NAME_USE SidUse;
DWORD cchTmpUsername = cchUsername;
DWORD cchTmpDomain = cchDomain;
if (!LookupAccountSidW(
NULL, // Local computer
pSid, // Security identifier for user
szUsername, // User name
&cchTmpUsername, // Size of user name
szDomain, // Domain name
&cchTmpDomain, // Size of domain name
&SidUse)) // Account type
{
dwResult = GetLastError();
hr = HRESULT_FROM_WIN32(dwResult);
wprintf_s(L"\n LookupAccountSidLocalW failed: hr = 0x%x\n", hr);
return hr;
}
// Combine the domain and user names.
swprintf_s(
szDomainAndUser,
cchDomainAndUser,
L"%s\\%s",
szDomain,
szUsername);
// Call CredPackAuthenticationBufferW once to determine the size,
// in bytes, of the authentication buffer.
if (!CredPackAuthenticationBufferW(
0, // Reserved
szDomainAndUser, // Domain\User name
szPassword, // User Password
NULL, // Packed credentials
&cbInAuthBlob) // Size, in bytes, of credentials
&& GetLastError() != ERROR_INSUFFICIENT_BUFFER)
{
dwResult = GetLastError();
hr = HRESULT_FROM_WIN32(dwResult);
wprintf_s(L"\n CredPackAuthenticationBufferW (1) failed: ");
wprintf_s(L"hr = 0x%x\n", hr);
}
// Allocate memory for the input buffer.
pvInAuthBlob = CoTaskMemAlloc(cbInAuthBlob);
if (!pvInAuthBlob)
{
cbInAuthBlob = 0;
wprintf_s(L"\n CoTaskMemAlloc() Out of memory.\n");
return HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY);
}
// Call CredPackAuthenticationBufferW again to retrieve the
// authentication buffer.
if (!CredPackAuthenticationBufferW(
0,
szDomainAndUser,
szPassword,
(PBYTE)pvInAuthBlob,
&cbInAuthBlob))
{
dwResult = GetLastError();
hr = HRESULT_FROM_WIN32(dwResult);
wprintf_s(L"\n CredPackAuthenticationBufferW (2) failed: ");
wprintf_s(L"hr = 0x%x\n", hr);
goto e_Exit;
}
// Display a dialog box to request credentials.
ui.cbSize = sizeof(ui);
ui.hwndParent = GetConsoleWindow();
ui.pszMessageText = WINBIO_CREDPROV_TEST_PASSWORD_PROMPT_MESSAGE;
ui.pszCaptionText = WINBIO_CREDPROV_TEST_PASSWORD_PROMPT_CAPTION;
ui.hbmBanner = NULL;
dwResult = CredUIPromptForWindowsCredentialsW(
&ui, // Customizing information
0, // Error code to display
&ulAuthPackage, // Authorization package
pvInAuthBlob, // Credential byte array
cbInAuthBlob, // Size of credential input buffer
&pvAuthBlob, // Output credential byte array
&cbAuthBlob, // Size of credential byte array
&fSave, // Select the save check box.
CREDUIWIN_IN_CRED_ONLY |
CREDUIWIN_ENUMERATE_CURRENT_USER
);
if (dwResult != NO_ERROR)
{
hr = HRESULT_FROM_WIN32(dwResult);
wprintf_s(L"\n CredUIPromptForWindowsCredentials failed: ");
wprintf_s(L"0x%08x\n", dwResult);
goto e_Exit;
}
*ppvAuthBlob = pvAuthBlob;
*pcbAuthBlob = cbAuthBlob;
e_Exit:
// Delete the input authentication byte array.
if (pvInAuthBlob)
{
SecureZeroMemory(pvInAuthBlob, cbInAuthBlob);
CoTaskMemFree(pvInAuthBlob);
pvInAuthBlob = NULL;
};
return hr;
}
//------------------------------------------------------------------------
// The following function retrieves the identity of the current user.
// This is a helper function and is not part of the Windows Biometric
// Framework API.
//
HRESULT GetCurrentUserIdentity(__inout PWINBIO_IDENTITY Identity)
{
// Declare variables.
HRESULT hr = S_OK;
HANDLE tokenHandle = NULL;
DWORD bytesReturned = 0;
struct{
TOKEN_USER tokenUser;
BYTE buffer[SECURITY_MAX_SID_SIZE];
} tokenInfoBuffer;
// Zero the input identity and specify the type.
ZeroMemory( Identity, sizeof(WINBIO_IDENTITY));
Identity->Type = WINBIO_ID_TYPE_NULL;
// Open the access token associated with the
// current process
if (!OpenProcessToken(
GetCurrentProcess(), // Process handle
TOKEN_READ, // Read access only
&tokenHandle)) // Access token handle
{
DWORD win32Status = GetLastError();
wprintf_s(L"Cannot open token handle: %d\n", win32Status);
hr = HRESULT_FROM_WIN32(win32Status);
goto e_Exit;
}
// Zero the tokenInfoBuffer structure.
ZeroMemory(&tokenInfoBuffer, sizeof(tokenInfoBuffer));
// Retrieve information about the access token. In this case,
// retrieve a SID.
if (!GetTokenInformation(
tokenHandle, // Access token handle
TokenUser, // User for the token
&tokenInfoBuffer.tokenUser, // Buffer to fill
sizeof(tokenInfoBuffer), // Size of the buffer
&bytesReturned)) // Size needed
{
DWORD win32Status = GetLastError();
wprintf_s(L"Cannot query token information: %d\n", win32Status);
hr = HRESULT_FROM_WIN32(win32Status);
goto e_Exit;
}
// Copy the SID from the tokenInfoBuffer structure to the
// WINBIO_IDENTITY structure.
CopySid(
SECURITY_MAX_SID_SIZE,
Identity->Value.AccountSid.Data,
tokenInfoBuffer.tokenUser.User.Sid
);
// Specify the size of the SID and assign WINBIO_ID_TYPE_SID
// to the type member of the WINBIO_IDENTITY structure.
Identity->Value.AccountSid.Size = GetLengthSid(tokenInfoBuffer.tokenUser.User.Sid);
Identity->Type = WINBIO_ID_TYPE_SID;
e_Exit:
if (tokenHandle != NULL)
{
CloseHandle(tokenHandle);
}
return hr;
}
자격 증명 제거
다음 코드 예제:
- GetCurrentUserIdentity를 호출하여 현재 사용자의 WINBIO_IDENTITY 개체를 검색합니다. GetCurrentUserIdentity는 도우미 함수이며 Windows 생체 인식 프레임워크의 일부가 아닙니다.
- WinBioRemoveCredential을 호출하여 저장소에서 자격 증명을 삭제합니다.
Winbio.lib 정적 라이브러리에 대한 이 함수 링크를 컴파일하고 다음 헤더 파일을 포함하려면 다음을 수행합니다.
- Windows.h
- Stdio.h
- Conio.h
- Winbio.h
HRESULT RemoveCredential()
{
HRESULT hr = S_OK;
WINBIO_IDENTITY identity;
// Find the identity of the user.
wprintf_s(L"\n Finding user identity.\n");
hr = GetCurrentUserIdentity( &identity );
if (FAILED(hr))
{
wprintf(L"\n User identity not found. hr = 0x%x\n", hr);
goto e_Exit;
}
// Remove the user credentials.
hr = WinBioRemoveCredential(identity, WINBIO_CREDENTIAL_PASSWORD);
if (FAILED(hr))
{
wprintf(L"\n WinBioRemoveCredential failed. hr = 0x%x\n", hr);
goto e_Exit;
}
wprintf_s(L"\n User credentials successfully removed.\n");
e_Exit:
wprintf_s(L"\n Press any key to exit...");
_getch();
return hr;
}
//------------------------------------------------------------------------
// The following function retrieves the identity of the current user.
// This is a helper function and is not part of the Windows Biometric
// Framework API.
//
HRESULT GetCurrentUserIdentity(__inout PWINBIO_IDENTITY Identity)
{
// Declare variables.
HRESULT hr = S_OK;
HANDLE tokenHandle = NULL;
DWORD bytesReturned = 0;
struct{
TOKEN_USER tokenUser;
BYTE buffer[SECURITY_MAX_SID_SIZE];
} tokenInfoBuffer;
// Zero the input identity and specify the type.
ZeroMemory( Identity, sizeof(WINBIO_IDENTITY));
Identity->Type = WINBIO_ID_TYPE_NULL;
// Open the access token associated with the
// current process
if (!OpenProcessToken(
GetCurrentProcess(), // Process handle
TOKEN_READ, // Read access only
&tokenHandle)) // Access token handle
{
DWORD win32Status = GetLastError();
wprintf_s(L"Cannot open token handle: %d\n", win32Status);
hr = HRESULT_FROM_WIN32(win32Status);
goto e_Exit;
}
// Zero the tokenInfoBuffer structure.
ZeroMemory(&tokenInfoBuffer, sizeof(tokenInfoBuffer));
// Retrieve information about the access token. In this case,
// retrieve a SID.
if (!GetTokenInformation(
tokenHandle, // Access token handle
TokenUser, // User for the token
&tokenInfoBuffer.tokenUser, // Buffer to fill
sizeof(tokenInfoBuffer), // Size of the buffer
&bytesReturned)) // Size needed
{
DWORD win32Status = GetLastError();
wprintf_s(L"Cannot query token information: %d\n", win32Status);
hr = HRESULT_FROM_WIN32(win32Status);
goto e_Exit;
}
// Copy the SID from the tokenInfoBuffer structure to the
// WINBIO_IDENTITY structure.
CopySid(
SECURITY_MAX_SID_SIZE,
Identity->Value.AccountSid.Data,
tokenInfoBuffer.tokenUser.User.Sid
);
// Specify the size of the SID and assign WINBIO_ID_TYPE_SID
// to the type member of the WINBIO_IDENTITY structure.
Identity->Value.AccountSid.Size = GetLengthSid(tokenInfoBuffer.tokenUser.User.Sid);
Identity->Type = WINBIO_ID_TYPE_SID;
e_Exit:
if (tokenHandle != NULL)
{
CloseHandle(tokenHandle);
}
return hr;
}