4 Stimmen

Hat jemand die Win32-API-Funktion CredWrite in .NET verwendet?

Ich versuche, die CredWrite sondern erhalten eine ERROR_INVALID_PARAMETER 87 (0x57) Fehler. Die Absicht ist es, einen sicheren Ort zu haben, um das Kennwort des Benutzers für meine .net WPF-Anwendung zu speichern.

Und mein Code:

public class CredMan
{
    private const string TARGET_PREFIX = "myappname:";

    public static void SavePassword(string username, string password)
    {
        Win32CredMan.Credential cred = new Win32CredMan.Credential();
        cred.Flags = 0;
        cred.Type = Win32CredMan.CRED_TYPE.GENERIC;
        cred.TargetName = TARGET_PREFIX + username;

        var encoding = new System.Text.UTF8Encoding();
        cred.CredentialBlob = encoding.GetBytes(password);
        cred.Persist = Win32CredMan.CRED_PERSIST.LOCAL_MACHINE;
        cred.UserName = username;

        bool isGood = Win32CredMan.CredWrite(cred, 0);
        int lastError = Marshal.GetLastWin32Error();

    }
}

Dies ist der Win32-Wrapper: (größtenteils entnommen aus pinvoke.net )

internal class Win32CredMan
{
    [DllImport("Advapi32.dll", EntryPoint = "CredReadW", CharSet = CharSet.Unicode, SetLastError = true)]
    public static extern bool CredRead(string target, CRED_TYPE type, int reservedFlag,
                      [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(CredentialInMarshaler))]out Credential credential);

    [DllImport("Advapi32.dll", EntryPoint = "CredFreeW", CharSet = CharSet.Unicode, SetLastError = true)]
    public static extern void CredFree(IntPtr buffer);

    [DllImport("Advapi32.dll", SetLastError = true, EntryPoint = "CredWriteW", CharSet = CharSet.Unicode)]
    public static extern bool CredWrite([In] Credential userCredential, [In] UInt32 flags);

    public enum CRED_TYPE : uint
    {
        GENERIC = 1,
        DOMAIN_PASSWORD = 2,
        DOMAIN_CERTIFICATE = 3,
        DOMAIN_VISIBLE_PASSWORD = 4,
        GENERIC_CERTIFICATE = 5,
        DOMAIN_EXTENDED = 6,
        MAXIMUM = 7,      // Maximum supported cred type
        MAXIMUM_EX = (MAXIMUM + 1000),  // Allow new applications to run on old OSes
    }
    public enum CRED_PERSIST : uint
    {
        SESSION = 1,
        LOCAL_MACHINE = 2,
        ENTERPRISE = 3,
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    public struct CREDENTIAL_ATTRIBUTE
    {
        string Keyword;
        uint Flags;
        uint ValueSize;
        IntPtr Value;
    }

    //This type is deliberately not designed to be marshalled.
    public class Credential
    {
        public UInt32 Flags;
        public CRED_TYPE Type;
        public string TargetName;
        public string Comment;
        public System.Runtime.InteropServices.ComTypes.FILETIME LastWritten;
        public byte[] CredentialBlob;
        public CRED_PERSIST Persist;
        public CREDENTIAL_ATTRIBUTE[] Attributes;
        public string TargetAlias;
        public string UserName;
    }
}

3voto

Herre Punkte 31

Ich bin jetzt auf das gleiche Problem gestoßen. Ich fand heraus, dass dieses Problem bei Verwendung der Option DOMAIN_PASSWORD als Anmeldeinformationstyp auftrat. Es stellte sich heraus, dass der TargetName einen falschen Wert enthielt.

Sie sollten nur die DNS- oder IP-Adresse angeben (Wildcard optional), aber NICHT eine vollständige URL oder ein Protokoll enthalten. z.B. "*.microsoft.com" ist korrekt, aber "http://www.microsoft.com/" ist UNGÜLTIG

Ich werde dies einfach hier posten, für den Fall, dass andere Leute auf dieses Problem stoßen. ich habe eine Weile gebraucht, um es zu finden.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X