Кто-нибудь использовал функцию Win32 API CredWrite в .NET?

Я пытаюсь использовать CredWrite, но получаю ошибку ERROR_INVALID_PARAMETER 87 (0x57). Цель состоит в том, чтобы иметь безопасное место для сохранения пароля пользователя для моего приложения .net WPF.

И мой код:

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();

    }
}

Это оболочка win32: (в основном взята с 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;
    }
}

person mlsteeves    schedule 08.03.2010    source источник
comment
Посмотрите здесь.... " title="credwrite возвращает код ошибки win32 2 ошибка неверная функция неправильная функция"> stackoverflow.com/questions/2337672/   -  person t0mm13b    schedule 08.03.2010
comment
Просто перечитайте код, и похоже, что класс Credential не сортируется (согласно комментарию).... да! :)   -  person mlsteeves    schedule 08.03.2010
comment
blogs.msdn.com/peerchan/pages/487834.aspx --Есть готовое решение, и оно работает.   -  person mlsteeves    schedule 08.03.2010


Ответы (1)


Я столкнулся с этой же проблемой сейчас. Я обнаружил, что эта проблема возникает при использовании параметра DOMAIN_PASSWORD в качестве типа учетных данных. Оказывается, TargetName содержит неверное значение.

вы должны указать только DNS или IP-адрес (необязательно подстановочный знак), но НЕ содержащий полный URL-адрес или протокол. например «*.microsoft.com» — правильно, но «http://www.microsoft.com/» — НЕДЕЙСТВИТЕЛЬНО

Я просто опубликую это здесь на случай, если другие люди столкнутся с этой проблемой. мне потребовалось некоторое время, чтобы найти его.

person Herre    schedule 26.05.2011
comment
К вашему сведению: ограничения на указание домена аналогичны ограничениям для функции OSX SecKeychainItemCreateFromContent, используемой со службами Keychain. - person Jason Harrison; 11.03.2016