Я работаю над школьным проектом, в котором я должен изменить способ предоставления учетных данных в пользовательском интерфейсе Windows Logon.
После некоторых поисков я нашел известные образцы Vista RTM (Longhorn) и Техническую документацию. Я обнаружил, что все примеры разработаны на C ++.
Поскольку у меня нет опыта работы с C / C ++, и я считаю себя приличным программистом C #, я хотел бы знать, возможно ли это сделать на C #.
Мне также нужно будет обмениваться данными с REST API для проверки логина, поэтому C # будет более дружественным.
Я нашел это https://stackoverflow.com/a/23496878/3626447, но информация, предоставленная @mageos, слишком «сырая».
Кто-нибудь знает некоторые полезные ресурсы?
Ссылка, которую вы предоставляете, полностью верна. Вам потребуется реализовать COM-объект в NET, который реализует следующие два COM-интерфейса (как минимум): ICredentialProvider, ICredentialProviderCredential
Сначала вам нужно будет представить их в .NET, чтобы вы могли ссылаться на них. Мой простой способ сделать это — пройти через IDL в Windows SDK. Файл idl, который вам понадобится, будет \Program Files (x86)\Windows Kits\10\Include\10.0.15063.0\um\credentialprovider.idl
,
Улов № 1: Вы должны обернуть все определения там в library CredentialProviders { ... }
заявление, только в противном случае немного из типов получим экспорт)
Откройте ваши собственные инструменты VS и скомпилируйте их с midl
:
midl "C:\Program Files (x86)\Windows Kits\10\Include\10.0.15063.0\um\credentialprovider.idl"
Это создаст библиотеку типов (файл tlb), которая затем может быть использована .NET для преобразования типов в типы C #. Теперь вы можете использовать tlbimp
Утилита для создания взаимодействия DLL, который затем можно использовать в .NET:
tlbimp.exe credentialprovider.tlb /out:CredentialProvider.Interop.dll
Улов № 2: Компиляция с tlbimp
к сожалению, удаляет возвращаемые типы для вызова метода (HRESULT
) и ожидает от вас использования подсистемы исключений .NET. Это не будет работать в этом случае, так как winlogon (или приложение хоста credUI) сбрасывает исключения и убивает процесс. Решение состоит в том, чтобы использовать утилиту, которая называется tlbimp2
, На момент написания статьи он размещен на SVN в codeplex — доступен только код. Мне пришлось загрузить код и перекомпилировать инструмент в VS2017 (я загрузил артефакты в прикрепленном репо). Итак, нам нужно запустить это для того, чтобы скомпилировать для winlogon:
tlbImp2.exe credentialprovider.tlb /out:CredentialProvider.Interop.dll /unsafe /verbose /preservesig
Теперь мы можем запустить библиотеку, которую мы можем реализовать из COM-объекта. Запустите проект DLL в .NET Framework. Отредактируйте проект и убедитесь, что установлен флажок «Зарегистрироваться для COM-взаимодействия». Ссылка на скомпилированную библиотеку Interop.
Как было сказано ранее, нам понадобятся два реализованных интерфейса: ICredentialProvider, ICredentialProviderCredential. Код должен выглядеть так:
[ComVisible(true)]
[Guid("<random-guid>")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface ITestWindowsCredentialProvider: ICredentialProvider
{
}
Вы можете сделать то же самое для интерфейса ICredentialProviderCredential.
По реализации:
[ComVisible(true)]
[Guid("<another-unique-id>")] // <-- This is what we are going to use for registration
[ClassInterface(ClassInterfaceType.None)]
public class TestWindowsCredentialProvider : ITestWindowsCredentialProvider
{
private const int E_NOTIMPL = unchecked((int) 0x80004001);
...
public int SetSerialization(ref _CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION pcpcs)
{
return E_NOTIMPL;
}
...
}
Возврат из всех методов E_NOTIMPL
и предоставить значения во всех out
параметры. Теперь у нас есть базовый объект, с которого мы можем начать. Вы можете отложить реализацию ICredentialProviderCredential до тех пор, пока не реализуете метод ICredentialProvider :: GetCredentialAt.
Вы можете зарегистрировать этот провайдер учетных данных, добавив ключ в настройках реестра. HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\Credential Providers
назван с помощью guid реализации компонента (запомните здесь фигурные скобки).
Когда вы это сделаете, служба входа в систему и вызовы credUI загрузят и запросят ваш компонент. Будьте предупреждены, однако: любое исключение приведет к сбою winlogon, из-за которого вы не сможете войти. Используйте ВМ как лучшую практику.
Теперь, после всех этих шагов, нам все еще нужно реализовать провайдер учетных данных. Это лучше всего описано в документе под названием Управляемый провайдером учетных данных Windows Logon Experience. В конечном итоге вам нужно будет согласовать пользовательский интерфейс с любыми возможными вещами, которые вам нужно будет сделать в фоновом режиме, и сопоставить его с пользователем.
Вы сможете войти в систему пользователя, когда правильно сериализуете информацию о пользователе по реализации метода ICredentialProviderCredential :: GetSerialization.
пример
Я сделал пример этого, и вы можете найти его здесь: https://github.com/phaetto/windows-credentials-provider
Других решений пока нет …