Windows Credential Provider in C#

早过忘川 提交于 2019-12-11 10:47:24

问题


i'm working on a school project where i'm supposed to modify the way credentials are provided in the windows Logon UI. After some of search i've found the famous Vista RTM (Longhorn) Samples and the Technical documentation. I've found that all the samples are developed in C++.

Since i don't have any C/C++ experience and i consider myself a decent C# programmer i would like to know if it is possible to do this C#.

I will also need to exchange data with a REST API to validate the login, so the C# would be more friendly.

I've found this https://stackoverflow.com/a/23496878/3626447, but the info provided by @mageos is too "raw".

Does anybody know some useful resources?


回答1:


The link that you provide is totally correct. You will need to implement a COM object in NET that implements the following two COM interfaces (at minimum): ICredentialProvider, ICredentialProviderCredential

First you will have to expose them in .NET so you can reference them. The easier way in my experience to do that is to go through IDL in windows SDK. The idl file that you will need will be \Program Files (x86)\Windows Kits\10\Include\10.0.15063.0\um\credentialprovider.idl.

Catch #1: You need to wrap all the definitions in there to the library CredentialProviders { ... } statement, otherwise only some of the types will get export)

Open your VS native tools and compile that with midl: midl "C:\Program Files (x86)\Windows Kits\10\Include\10.0.15063.0\um\credentialprovider.idl"

This will create a type library (tlb file) which can be then used by .NET to transpile the types to C# types. You can now use the tlbimp utility to create an interop dll that then you can use in .NET: tlbimp.exe credentialprovider.tlb /out:CredentialProvider.Interop.dll

Catch #2: The compilation with tlbimp unfortunately strips the return types for a method call (HRESULT) and expects you to use the .NET exception subsystem. This will not work in this case as winlogon (or credUI host app) rethrows the exceptions and kills the process. The solution is to use a utility that is called tlbimp2. At this time of writing it's hosted with SVN at codeplex - only the code is available. I had to download the code and recompile the tool in VS2017 (I have uploaded the artifacts in the attached repo). So we need to run this in order to compile for winlogon: tlbImp2.exe credentialprovider.tlb /out:CredentialProvider.Interop.dll /unsafe /verbose /preservesig

Now we can start a library that we can implement out COM object. Start a dll project in .NET framework. Edit the project and make sure that the flag "Register for COM interop" is selected. Reference the compiled Interop library.

As said before, we will need two interfaces implemented: ICredentialProvider, ICredentialProviderCredential. The code should look like this:

[ComVisible(true)]
[Guid("<random-guid>")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface ITestWindowsCredentialProvider: ICredentialProvider
{
}

You can do exactly the same for ICredentialProviderCredential interface.

On the implementation:

[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;
    }

    ...
}

Return from all methods E_NOTIMPL and provide values in all out parameters. Now we have a base object that we can start with. You can delay the implementation of the ICredentialProviderCredential until you implement the method ICredentialProvider::GetCredentialAt.

You can register this credential provider by adding a key under the registry setting HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\Credential Providers named with the component's implementation guid (remember the braces here).

When you do that the logon service and the credUI invocations will load and query your component. Be warned however: any exception will make the winlogon crash rendering you unable to login. Use a VM as best practice.

Now, after all those steps we still need to implement the credential provider. This is best described in a document called Credential Provider driven Windows Logon Experience. You will eventually need to orchestrate the UI with any possible things that you would need to do in the background and map it to a user.

You will be able to login a user when correctly serialize the user info on the method implementation ICredentialProviderCredential::GetSerialization.

Example

I have made an example of this and you can find it here: https://github.com/phaetto/windows-credentials-provider



来源:https://stackoverflow.com/questions/36425318/windows-credential-provider-in-c-sharp

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!