Credential Provider

Windows操作系统的登录

WinXP利用GINA机制来登录,从Vista开始采用新的登录机制,名为Credential Provider. 
 
在 Windows Vista 之前的环境中,每个会话都有一个 winlogon 实例,它负责控制该会话的交互式登录序列,它运行在Session 0. 计算机上已注册的 GINA 加载到 winlogon 进程空间中。(还可能加载一个称作“GINA 链接”的配置,但测试和支持这样的复杂配置很困难。)最后,GINA 调用 LogonUser 以及相关的身份验证 API。
 
在 Windows Vista 以后的系统中,Session 0 不再用于交互式登录.这有利于提高安全性,因为现在已有一个会话边界将所有的计算机进程与各个用户的进程分隔开来。此外,现在对内核全局命名空间的控制也更加严格,因为默认情况下由用户应用程序创建的对象已不在内核全局命名空间之内。
 
除Session 0 之外的每一个Session仍会有一个 winlogon 实例, 已通过新的 LogonUI 进程加载。
在由哪个组件负责显示登录图形界面方面也有一个重要的改动。以前,这是由 GINA 来处理的,因此,显示界面的工作可能一直由第三方组件来完成。在新的体系结构中,这是由操作系统的一个内置组件 LogonUI 来负责完成的。

新的Credential Provider机制由2部分组成

ICredentialProvider : 

以ICredentialProvider 为父类的Provider对象,初始化时LogonUI会调用SetUsageScenario 函数来初始化环境,然后调用GetCredentialCount,GetCredentialAt 来得到此Provider下的所有的Credential对象,再调用GetFieldDescriptorCount,GetFieldDescriptorAt来得到Credential的UI描述.注意UI描述对于同一个Provider下的Credential都是相同的.

ICredentialProviderCredential : 

以ICredentialProviderCredential 为父类的Credential对象,它表现为界面上某一个ICON区域.通过它,可以得到界面每个元素的类型和值.

ICredentialProviderFilter :

以ICredentialProviderFilter 为父类的Credential对象,它是一个过滤对象,可以指定在系统登录的时候,那些Provider是有效的,通过它可以实现只保留系统中一个或几个特殊Provider的效果.

Credential Provider注册

注册表结构类似如下形式

Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\Credential Providers\{F617AF08-2856-419c-B4E5-2889C6B71EA9}]
@="SSCredProvider"
[HKEY_CLASSES_ROOT\CLSID\{F617AF08-2856-419c-B4E5-2889C6B71EA9}]
@="SSCredProvider"
[HKEY_CLASSES_ROOT\CLSID\{F617AF08-2856-419c-B4E5-2889C6B71EA9}\InprocServer32]
@="E:\\Sources\\SourceRoot\\trunk\\win32\\bin.debug\\SSCredProvider.dll"
"ThreadingModel"="Apartment"
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\Credential Provider Filters\{F617AF08-2856-419c-B4E5-2889C6B71EA9}]
@="SSCredProvider"

有几点需要注意:

1. Credential一般存在于Provider中,必须动态创建,利用COM的AddRef和Release机制来操作其生命周期.
2.Credential通过GetSerialize来登录系统,调用Lsa系列函数,例如LsaConnectUntrusted等,结果如果为NTSTATUS,可以调用HRESULT_FROM_NT来判断是否成功,HRESULT要用SUCESSED宏,而不能直接比较是否等于S_OK.
3.关于FieldDescriptor.每个Provider下的Credentials共享相同的FieldDescriptor,即一个Credential有几个UI元素,其余的Credentials也必须有相同的个数,但是每个Credentials可以通过GetFieldState 来调整自己的UI元素的状态.
 

64bit 下的Vista Credential Provider问题

12-09

我的Vista Credential Provider在X86下运行正常,可以是到了64Bit下的时候Credential的Advise方法没有被调起来,所以凭证没有显示,下面是我抓下来的Log:rnrn@Time:: Entry DLLMain --> DLL_PROCESS_ATTACH(1) --> Initialize once for each new process.rnrn@Time:: Dll.cpp --> DllGetClassObject() ==== CreateInstance of IClassFactoryrnrn@Time:: Dll.cpp --> CClassFactory_CreateInstance()rnrn@Time:: Dll.cpp --> CLSID == CLSID_CSampleProvider then Invoke CClassFactory()rnrn@Dll.cpp --> CClassFactory:CClassFactory() Current _cRef is: ------ 1rnrn@Time:: Dll.cpp --> CClassFactory:QueryInterface() rnrn@Time:: Dll.cpp --> CClassFactory:QueryInterface() IID == IID_IClassFactoryrnrn@Dll.cpp --> CClassFactory:AddRef() Current _cRef is ------ 2rnrn@Dll.cpp --> CClassFactory:Release() Current _cRef is ------ 1rnrn@Time:: Dll.cpp --> CClassFactory:CreateInstance() To Create a Provider Instance.rnrn@Time:: CSampleProvider.cpp --> CSampleProvider::CSampleProvider_CreateInstance ===> Create a sample providerrnrn@CSampleProvider.cpp --> CSampleProvider::CSampleProvider() Current _cRef = ------ 1rnrn@Dll.cpp --> DllAddRef() Current g_cRef = ------ 1rnrn@Time:: CSampleProvider.cpp --> CSampleProvider::CSampleProvider() _pCredential = NULLrnrn@Time:: CSampleProvider.cpp --> CSampleProvider::QueryInterface()rnrn@Time:: CSampleProvider.cpp --> CSampleProvider::QueryInterface() IID_ICredentialProvider == riidrnrn@CSampleProvider.cpp --> CSampleProvider::AddRef() ==== Current _cRef is ------ 2rnrn@CSampleProvider.cpp --> CSampleProvider::Release() ==== Current _cRef is ------ 1rnrn@CSampleProvider.cpp --> CSampleProvider::AddRef() ==== Current _cRef is ------ 2rnrn@CSampleProvider.cpp --> CSampleProvider::Release() ==== Current _cRef is ------ 1rnrn@Dll.cpp --> CClassFactory:Release() Current _cRef is ------ 0rnrn@Time:: CSampleProvider.cpp --> CSampleProvider::QueryInterface()rnrn@Time:: CSampleProvider.cpp --> CSampleProvider::QueryInterface() IID_ICredentialProvider == riidrnrn@CSampleProvider.cpp --> CSampleProvider::AddRef() ==== Current _cRef is ------ 2rnrn@CSampleProvider.cpp --> CSampleProvider::Release() ==== Current _cRef is ------ 1rnrn@CSampleProvider.cpp --> CSampleProvider::AddRef() ==== Current _cRef is ------ 2rnrn@CSampleProvider.cpp --> CSampleProvider::Release() ==== Current _cRef is ------ 1rnrn@CSampleProvider.cpp --> CSampleProvider::SetUsageScenario() cpus == ------ 1rnrn@CSampleProvider.cpp --> CSampleProvider::SetUsageScenario() dwFlags == ------ 0rnrn@Time:: CSampleProvider.cpp --> CSampleProvider::SetUsageScenario() Create a new SampleCredentialrnrn@Time:: CSampleCredential.cpp --> CSampleCredential::CSampleCredential Contructorrnrn@Dll.cpp --> DllAddRef() Current g_cRef = ------ 2rnrn@Time:: CSampleProvider.cpp --> CSampleProvider::SetUsageScenario() Initialize SampleCredentialrnrn@Time:: CSampleCredential.cpp --> CSampleCredential::Initialize()rnrn@Time:: CSampleProvider.cpp --> CSampleProvider::Advise()rnrn@CSampleProvider.cpp --> CSampleProvider::GetCredentialCount = ------ 1rnrn@CSampleProvider.cpp --> CSampleProvider::GetCredentialAt = ------ 0rnrn@CSampleProvider.cpp --> CSampleProvider::GetFieldDescriptorCount() --> FieldDescriptorCount = ------ 10rnrn@CSampleProvider.cpp --> CSampleProvider::GetFieldDescriptorAt = ------ 0rnrn@CSampleProvider.cpp --> CSampleProvider::GetFieldDescriptorAt = ------ 1rnrn@CSampleProvider.cpp --> CSampleProvider::GetFieldDescriptorAt = ------ 2rnrn@CSampleProvider.cpp --> CSampleProvider::GetFieldDescriptorAt = ------ 3rnrn@CSampleProvider.cpp --> CSampleProvider::GetFieldDescriptorAt = ------ 4rnrn@CSampleProvider.cpp --> CSampleProvider::GetFieldDescriptorAt = ------ 5rnrn@CSampleProvider.cpp --> CSampleProvider::GetFieldDescriptorAt = ------ 6rnrn@CSampleProvider.cpp --> CSampleProvider::GetFieldDescriptorAt = ------ 7rnrn@CSampleProvider.cpp --> CSampleProvider::GetFieldDescriptorAt = ------ 8rnrn@CSampleProvider.cpp --> CSampleProvider::GetFieldDescriptorAt = ------ 9rnrn@Time:: CSampleCredential.cpp --> CSampleCredential::GetBitmapValue()rnrn@Time:: CSampleCredential.cpp --> CSampleCredential::GetFieldState()rnrn@Time:: CSampleCredential.cpp --> CSampleCredential::GetStringValue()rnrn@Time:: CSampleCredential.cpp --> CSampleCredential::GetFieldState()rnrn@Time:: CSampleCredential.cpp --> CSampleCredential::GetStringValue()rnrn@Time:: CSampleCredential.cpp --> CSampleCredential::GetFieldState()rnrn@Time:: CSampleCredential.cpp --> CSampleCredential::GetStringValue()rnrn@Time:: CSampleCredential.cpp --> CSampleCredential::GetFieldState()rnrn@Time:: CSampleCredential.cpp --> CSampleCredential::GetStringValue()rnrn@Time:: CSampleCredential.cpp --> CSampleCredential::GetFieldState()rnrn@Time:: CSampleCredential.cpp --> CSampleCredential::GetSubmitButtonValue()rnrn@Time:: CSampleCredential.cpp --> CSampleCredential::GetFieldState()rnrn@Time:: CSampleCredential.cpp --> CSampleCredential::GetCheckboxValue()rnrn@Time:: CSampleCredential.cpp --> CSampleCredential::GetFieldState()rnrn@Time:: CSampleCredential.cpp --> CSampleCredential::GetComboBoxValueCount()rnrn@CSampleCredential.cpp --> CSampleCredential::GetComboBoxValueAt == ------ 7rnrn@CSampleCredential.cpp --> CSampleCredential::GetComboBoxValueAt == ------ 7rnrn@CSampleCredential.cpp --> CSampleCredential::GetComboBoxValueAt == ------ 7rnrn@CSampleCredential.cpp --> CSampleCredential::GetComboBoxValueAt == ------ 7rnrn@Time:: CSampleCredential.cpp --> CSampleCredential::GetFieldState()rnrn@Time:: CSampleCredential.cpp --> CSampleCredential::GetStringValue()rnrn@Time:: CSampleCredential.cpp --> CSampleCredential::GetFieldState()rnrn@Time:: CSampleCredential.cpp --> CSampleCredential::GetCheckboxValue()rnrn@Time:: CSampleCredential.cpp --> CSampleCredential::GetFieldState()rnrnrnrn$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$4rnrn### Time:: CSampleCredential.cpp --> CSampleCredential::Advise()rnrn### Time:: CSampleCredential.cpp --> CSampleCredential::SetSelected()rnrn### Time:: CSampleCredential.cpp --> CSampleCredential::UnAdvise()rnrn### Time:: CSampleCredential.cpp --> CSampleCredential::Advise()rnrn### Time:: CSampleCredential.cpp --> CSampleCredential::SetStringValue()rnrn### Time:: CSampleCredential.cpp --> CSampleCredential::UnAdvise()rnrn### Time:: CSampleCredential.cpp --> CSampleCredential::Advise()rnrn### Time:: CSampleCredential.cpp --> CSampleCredential::SetStringValue()rnrn### Time:: CSampleCredential.cpp --> CSampleCredential::UnAdvise()rnrn### Time:: CSampleCredential.cpp --> CSampleCredential::Advise()rnrn### Time:: CSampleCredential.cpp --> CSampleCredential::SetStringValue()rnrn### Time:: CSampleCredential.cpp --> CSampleCredential::UnAdvise()rnrn### Time:: CSampleCredential.cpp --> CSampleCredential::Advise()rnrn### Time:: CSampleCredential.cpp --> CSampleCredential::GetSerialization()rnrn### Time:: CSampleCredential.cpp --> CSampleCredential::UnAdvise()rnrn$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$4rnrnrn@Time:: CSampleProvider.cpp --> CSampleProvider::UnAdvise()rnrnrnrnrnrn$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$4rnrn### Time:: CSampleCredential.cpp --> CSampleCredential::Advise()rnrn### Time:: CSampleCredential.cpp --> CSampleCredential::ReportResult()rnrn### Time:: CSampleCredential.cpp --> CSampleCredential::UnAdvise()rnrn$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$4rnrnrnrn@CSampleProvider.cpp --> CSampleProvider::Release() ==== Current _cRef is ------ 0rnrn@Time:: Dll.cpp --> DllCanUnloadNow()rnrn@Time:: Dll.cpp --> DllCanUnloadNow() ==== cocreated objects still exist, don't unloadrnrn@Time:: Entry DLLMain --> DLL_PROCESS_DETACH --> Perform any necessary cleanup.rnrn注:rn以@开头的为32bit和64bit都生产的Logrn以###开头的为只在32Bit下产生的log,64bit下没有,贴出来是为了比较。rnrn请高手们指点一下,为什么 CSampleCredential::Advise()在64bit下面没有被调起来?rn照道理组件已经是被加载进来的了,请高手们指点下,万分感谢!! 论坛

Credential Provider增加一个输入密码的编辑框

09-28

我希望增加一个输入密码的编辑框,要与SERVER做认证用rn以下是我修改微软提供的五个示例程序的SampleCredUICredentialProvider中的common.h,//ADD为我新增的rnrn#pragma oncern#include rn#include rn#define SECURITY_WIN32rn#include rn#include rnrn#define MAX_ULONG ((ULONG)(-1))rnrn// The indexes of each of the fields in our credential provider's tiles.rnenum SAMPLE_FIELD_ID rnrn SFI_TILEIMAGE = 0,rn SFI_USERNAME = 1,rn SFI_PASSWORD = 2,rn SFI_SBOX = 3, //ADDrn SFI_SUBMIT_BUTTON = 4, rn SFI_NUM_FIELDS = 5, // Note: if new fields are added, keep NUM_FIELDS last. This is used as a count of the number of fieldsrn;rnrn// The first value indicates when the tile is displayed (selected, not selected)rn// the second indicates things like whether the field is enabled, whether it has key focus, etc.rnstruct FIELD_STATE_PAIRrnrn CREDENTIAL_PROVIDER_FIELD_STATE cpfs;rn CREDENTIAL_PROVIDER_FIELD_INTERACTIVE_STATE cpfis;rn;rnrn// These two arrays are seperate because a credential provider mightrn// want to set up a credential with various combinations of field state pairs rn// and field descriptors.rnrn// The field state value indicates whether the field is displayedrn// in the selected tile, the deselected tile, or both.rn// The Field interactive state indicates when rnstatic const FIELD_STATE_PAIR s_rgFieldStatePairs[] = rnrn CPFS_DISPLAY_IN_BOTH, CPFIS_NONE , // SFI_TILEIMAGErn CPFS_DISPLAY_IN_BOTH, CPFIS_NONE , // SFI_USERNAMErn CPFS_DISPLAY_IN_SELECTED_TILE, CPFIS_FOCUSED , // SFI_PASSWORDrn CPFS_DISPLAY_IN_SELECTED_TILE, CPFIS_NONE , // SFI_SUBMIT_BUTTON rn;rnrn// Field descriptors for unlock and logon.rn// The first field is the index of the field.rn// The second is the type of the field.rn// The third is the name of the field, NOT the value which will appear in the field.rnstatic const CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR s_rgCredProvFieldDescriptors[] =rnrn SFI_TILEIMAGE, CPFT_TILE_IMAGE, L"Image" ,rn SFI_USERNAME, CPFT_LARGE_TEXT, L"Username" ,rn SFI_PASSWORD, CPFT_PASSWORD_TEXT, L"Password" ,rn SFI_SBOX, CPFT_PASSWORD_TEXT, L"SBOX" , //ADDrn SFI_SUBMIT_BUTTON, CPFT_SUBMIT_BUTTON, L"Submit" ,rn;rnrn因为我是初学者,希望有高手可以替我说明一下,我接下来该如何做吗? 论坛

没有更多推荐了,返回首页