我正在尝试以编程方式将onetoone客户端证书身份验证添加到applicationhost.config文件中。
在引用这两个文档(thread1,thread2)后,我确信可以用不同的语言实现它。出于某种原因,我必须用C ++开发它。在thread1中翻译代码示例时,
以下是代码段FYI。
#include "stdafx.h"
#include <windows.h>
#include <stdio.h>
#include <ahadmin.h>
#include <crtdbg.h>
#include <string>
using namespace std;
void PrintPropertiesOfElement(IAppHostElement *pElement)
{
HRESULT hr = S_OK;
IAppHostPropertyCollection *pProperties = NULL;
IAppHostProperty *pProperty = NULL;
hr = pElement->get_Properties(&pProperties);
DWORD properties_count = 0;
hr = pProperties->get_Count(&properties_count);
VARIANT vtIndex;
vtIndex.vt = VT_INT;
for(DWORD i=0; i<properties_count; ++i)
{
vtIndex.intVal = i;
hr = pProperties->get_Item(vtIndex, &pProperty);
BSTR strName;
BSTR strValue;
hr = pProperty->get_Name(&strName);
hr = pProperty->get_StringValue(&strValue);
_tprintf(_T("name : %s, value: %s\n"), strName, strValue);
}
}
void PrintElementsOfCollection(IAppHostChildElementCollection *pCollection)
{
HRESULT hr = S_OK;
IAppHostElement *pElement = NULL;
DWORD elements_count = 0;
hr = pCollection->get_Count(&elements_count);
VARIANT vtIndex;
vtIndex.vt = VT_INT;
for(DWORD i=0; i<elements_count; ++i)
{
vtIndex.intVal = i;
hr = pCollection->get_Item(vtIndex, &pElement);
BSTR strName;
hr = pElement->get_Name(&strName);
_tprintf(_T("element : %s\n"), strName);
}
}
void PrintElementsOfCollection(IAppHostElementCollection *pCollection)
{
HRESULT hr = S_OK;
IAppHostElement *pElement = NULL;
DWORD elements_count = 0;
hr = pCollection->get_Count(&elements_count);
VARIANT vtIndex;
vtIndex.vt = VT_INT;
for(DWORD i=0; i<elements_count; ++i)
{
vtIndex.intVal = i;
hr = pCollection->get_Item(vtIndex, &pElement);
BSTR strName;
hr = pElement->get_Name(&strName);
_tprintf(_T("element : %s\n"), strName);
//PrintPropertiesOfElement(pElement);
}
}
struct UserCertification
{
VARIANT username;
VARIANT password;
VARIANT certification;
public:
UserCertification(wstring name, wstring pwd, wstring cert)
{
username.vt = VT_BSTR;
username.bstrVal = SysAllocString(name.c_str());
password.vt = VT_BSTR;
password.bstrVal = SysAllocString(pwd.c_str());
certification.vt = VT_BSTR;
certification.bstrVal = SysAllocString(cert.c_str());
}
};
HRESULT SetHostElementProperty(IAppHostElement *pElement, UserCertification *pUserCert)
{
HRESULT hr = S_OK;
IAppHostProperty *pProperty = NULL;
BSTR name = SysAllocString(L"userName");
BSTR password = SysAllocString(L"password");
BSTR certification = SysAllocString(L"certificate");
//name
hr = pElement->GetPropertyByName(name, &pProperty);
pProperty->put_Value(pUserCert->username);
//password
hr = pElement->GetPropertyByName(password, &pProperty);
pProperty->put_Value(pUserCert->password);
//certification
hr = pElement->GetPropertyByName(certification, &pProperty);
pProperty->put_Value(pUserCert->certification);
return hr;
}
UserCertification* GenerateUserCertification()
{
wstring username = L"jinqiu.tao@emacle.com";
wstring password = L"123456";
wstring certificate = L"xxxxxxxx";
return new UserCertification(username, password, certificate);
}
int _tmain(int argc, _TCHAR* argv[])
{
HRESULT hr = S_OK;
IAppHostWritableAdminManager * pWMgr = NULL;
IAppHostConfigManager * pCfgMgr = NULL;
IAppHostConfigFile * pCfgFile = NULL;
IAppHostConfigLocationCollection * pLocations = NULL;
IAppHostElement *pAdminSection = NULL;
IAppHostElementCollection *pElementCollection = NULL;
IAppHostChildElementCollection *pChildElements = NULL;
IAppHostElement *pElement = NULL;
IAppHostElement *pNewElement = NULL;
BSTR bstrConfigCommitPath = SysAllocString(L"MACHINE/WEBROOT/APPHOST/Default Web Site");
BSTR bstrSectionName = SysAllocString(L"system.webServer/security/authentication/iisClientCertificateMappingAuthentication");
BSTR bstrOneToOne = SysAllocString(L"oneToOneMappings");
BSTR bstrElementName = SysAllocString(L"add");
// Initialize
hr = CoInitializeEx( NULL, COINIT_MULTITHREADED );
// Create
hr = CoCreateInstance( __uuidof( AppHostWritableAdminManager ), NULL,
CLSCTX_INPROC_SERVER,
__uuidof( IAppHostWritableAdminManager ), (void**) &pWMgr );
pWMgr -> put_CommitPath ( bstrConfigCommitPath );
hr = pWMgr->GetAdminSection(bstrSectionName, bstrConfigCommitPath, &pAdminSection);
hr = pAdminSection->get_ChildElements(&pChildElements);
PrintElementsOfCollection(pChildElements);
hr = pAdminSection->GetElementByName(bstrOneToOne, &pElement);
hr = pElement->get_Collection(&pElementCollection);
//PrintElementsOfCollection(pElementCollection);
hr = pElementCollection->CreateNewElement(bstrElementName, &pNewElement);
//PrintPropertiesOfElement(pNewElement);
hr = SetHostElementProperty(pNewElement, GenerateUserCertification());
//got and error saying that another process is accesssing the data
hr = pElementCollection->AddElement(pNewElement); //got an error code 0x80070021 here |||||||||||||||||
PrintElementsOfCollection(pElementCollection);
// Commit the changes to the configuration system
pWMgr->CommitChanges ( );
return 0;
}
如您所见,我可以创建一个新元素,但无法将其添加到元素集合中。
我想要做的只是在onetoonemappings部分添加一条记录。
<location path="Default Web Site">
<system.webServer>
<security>
<access sslFlags="None" />
<authentication>
<anonymousAuthentication enabled="true" />
<iisClientCertificateMappingAuthentication enabled="true" oneToOneCertificateMappingsEnabled="true">
<oneToOneMappings>
<add userName="yonggui.yu@emacle.com" password="[enc:AesProvider:4QEVwn3c530VH5sdwCl+Sm8G2eJesNEs4SaL6U5LrXg=:enc]" certificate="MIIFOjCCBCKgAwIBAgIKOAV" />
<add userName="yuyonggui@tbp.com" password="[enc:AesProvider:iBqmPwvbefiuiUZ03AyPD/0AxzD0HIb4SlJXKQGr9Ug=:enc]" certificate="MIIEjzCCA3egAwIBAgIKGgSFpwAAAA" />
<add userName="yonggui.yu@emacle.com" password="[enc:AesProvider:DogNZMKGrLa9ih2IO9PiMNUz9Ucggu9icKD7o8+U8dQ=:enc]" certificate="MIIFZzCCBE+gAwIBAgIHGAOD3e2==" />
</oneToOneMappings>
</iisClientCertificateMappingAuthentication>
</authentication>
</security>
</system.webServer>
我希望我已经说清楚了。如果您需要任何其他信息,请随时通知我。
期待您的帮助。
最诚挚的问候,
约旦