代码之家  ›  专栏  ›  技术社区  ›  mlsteeves

有人在.net中使用过win32 api函数credwrite吗?

  •  3
  • mlsteeves  · 技术社区  · 16 年前

    我想用 CredWrite 但是得到一个 ERROR_INVALID_PARAMETER 87 (0x57) 错误。其目的是要有一个安全的地方来保存用户的密码。

    我的代码:

    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;
        }
    }
    
    1 回复  |  直到 16 年前
        1
  •  3
  •   Herre    15 年前

    我现在也遇到了同样的问题。 我发现使用域密码选项作为凭据类型时出现此问题。 结果发现targetname包含不正确的值。

    您应该只指定dns或ip地址(通配符可选)。 但不包含完整的url或协议。 例如,“*.microsoft.com”是正确的,但是“http://www.microsoft.com/”是无效的

    我会把这个贴在这里,以防其他人碰到这个问题。我花了点时间才找到它。