Поставщик учетных данных Windows в C#

я работаю над школьным проектом, где я должен изменить способ предоставления учетных данных в пользовательском интерфейсе входа в систему Windows. После некоторых поисков я нашел знаменитые образцы Vista RTM (Longhorn) и техническую документацию. Я обнаружил, что все образцы разработаны на C++.

Поскольку у меня нет опыта работы с C/C++, и я считаю себя приличным программистом на C#, я хотел бы знать, возможно ли это сделать на C#.

Мне также нужно будет обмениваться данными с REST API для проверки входа в систему, поэтому C # будет более удобным.

Я нашел это https://stackoverflow.com/a/23496878/3626447, но информация, предоставленная @mageos слишком "сырой".

Кто-нибудь знает полезные ресурсы?


person loveMeansNothing    schedule 05.04.2016    source источник
comment
pgina.org и написать плагин — самый простой способ, если это допустимо.   -  person Alex K.    schedule 05.04.2016
comment
К сожалению, это не @Alex K. Это был мой первый подход, но мне не разрешили.   -  person loveMeansNothing    schedule 05.04.2016
comment
Удалось ли вам найти что-нибудь полезное @loveMeansNothing? я тоже в одной лодке   -  person Nitin Khubani    schedule 13.06.2017


Ответы (1)


Ссылка, которую вы даете, полностью верна. Вам потребуется реализовать 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, названный в соответствии с руководством по реализации компонента (помните здесь фигурные скобки).

Когда вы это сделаете, служба входа в систему и вызовы credUI будут загружать и запрашивать ваш компонент. Однако имейте в виду: любое исключение приведет к сбою winlogon, из-за которого вы не сможете войти в систему. Лучше всего использовать виртуальную машину.

Теперь, после всех этих шагов, нам все еще нужно реализовать поставщика учетных данных. Это лучше всего описано в документе под названием Опыт входа в Windows на основе поставщика учетных данных. В конечном итоге вам нужно будет организовать пользовательский интерфейс с любыми возможными вещами, которые вам нужно будет делать в фоновом режиме, и сопоставить их с пользователем.

Вы сможете войти в систему пользователя, если правильно сериализуете информацию о пользователе в реализации метода ICredentialProviderCredential::GetSerialization.

Example

Я сделал пример этого, и вы можете найти его здесь: https://github.com/phaetto/windows-credentials-provider

person Alexander Mantzoukas    schedule 25.08.2017