zhangbinmy 发表于 2018-6-19 12:17:41

C#代码实现对Windows凭据的管理

  
private void button1_Click(object sender, EventArgs e)         {
  //ip地址或者网络路径 例如:TERMSRV/192.168.2.222
  string key = txtIP.Text.Trim();
  string userName = txtUserName.Text.Trim();
  string password = txtPassword.Text.Trim();
  //用于标记凭据添加是否成功 i=0:添加成功;i=1:添加失败
  int i = 0;
  try{
  i = NativeCredMan.WriteCred(key,
  userName,
  password,
  CRED_TYPE.DOMAIN_PASSWORD,
  CRED_PERSIST.LOCAL_MACHINE);
  }
  catch{
  i = 1;
  }
  if (i == 0)
  txtMsg.Text = "添加成功";
  else
  txtMsg.Text = "添加失败";
  
}
  
/// <summary>
  
/// 凭据类型
  
/// </summary>
  
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,
  
}
  

  
internal class NativeCredMan
  
{
  
   
  
    //读取凭据信息
  
    static extern bool CredRead(string target, CRED_TYPE type, int reservedFlag, out IntPtr CredentialPtr);
  

  
   
  
    //增加凭据
  
    static extern bool CredWrite( ref NativeCredential userCredential, UInt32 flags);
  

  
   
  
    static extern bool CredFree( IntPtr cred);
  

  
   
  
    //删除凭据
  
    static extern bool CredDelete(string target, CRED_TYPE type, int flags);
  

  
    //
  
    //static extern bool CredEnumerateold(string filter, int flag, out int count, out IntPtr pCredentials);
  

  
   
  
    public static extern bool CredEnumerate(string filter, uint flag, out uint count, out IntPtr pCredentials);
  

  
   
  
    private struct NativeCredential{
  
      public UInt32 Flags;
  
      public CRED_TYPE Type;
  
      public IntPtr TargetName;
  
      public IntPtr Comment;
  
      public System.Runtime.InteropServices.ComTypes.FILETIME LastWritten;
  
      public UInt32 CredentialBlobSize;
  
      public IntPtr CredentialBlob;
  
      public UInt32 Persist;
  
      public UInt32 AttributeCount;
  
      public IntPtr Attributes;
  
      public IntPtr TargetAlias;
  
      public IntPtr UserName;
  
      internal static NativeCredential GetNativeCredential(Credential cred)
  
      {
  
            var ncred = new NativeCredential
  
            {
  
                AttributeCount = 0,
  
                Attributes = IntPtr.Zero,
  
                Comment = IntPtr.Zero,
  
                TargetAlias = IntPtr.Zero,
  
                //Type = CRED_TYPE.DOMAIN_PASSWORD,
  
                Type=cred.Type,
  
                Persist = (UInt32)cred.Persist,
  
                CredentialBlobSize = (UInt32)cred.CredentialBlobSize,
  
                TargetName = Marshal.StringToCoTaskMemUni(cred.TargetName),
  
                CredentialBlob = Marshal.StringToCoTaskMemUni(cred.CredentialBlob),
  
                UserName = Marshal.StringToCoTaskMemUni(cred.UserName)
  
            };
  
            return ncred;
  
      }
  
    }
  

  
   
  
    public struct Credential{
  
      public UInt32 Flags;
  
      public CRED_TYPE Type;
  
      public string TargetName;
  
      public string Comment;
  
      public System.Runtime.InteropServices.ComTypes.FILETIME LastWritten;
  
      public UInt32 CredentialBlobSize;
  
      public string CredentialBlob;
  
      public CRED_PERSIST Persist;
  
      public UInt32 AttributeCount;
  
      public IntPtr Attributes;
  
      public string TargetAlias;
  
      public string UserName;
  
      }
  
    /// <summary>
  
    /// 向添加计算机的凭据管理其中添加凭据
  
    /// </summary>
  
    /// <param name="key">internet地址或者网络地址</param>
  
    /// <param name="userName">用户名</param>
  
    /// <param name="secret">密码</param>
  
    /// <param name="type">密码类型</param>
  
    /// <param name="credPersist"></param>
  
    /// <returns></returns>
  
    public static int WriteCred(string key, string userName, string secret, CRED_TYPE type, CRED_PERSIST credPersist)
  
    {
  
      var byteArray = Encoding.Unicode.GetBytes(secret);
  
      if (byteArray.Length > 512)
  
            throw new ArgumentOutOfRangeException("The secret message has exceeded 512 bytes.");
  
      var cred = new Credential
  
      {
  
         TargetName = key,
  
         CredentialBlob = secret,
  
         CredentialBlobSize = (UInt32)Encoding.Unicode.GetBytes(secret).Length,
  
         AttributeCount = 0,
  
         Attributes = IntPtr.Zero,
  
         UserName = userName,
  
         Comment = null,
  
         TargetAlias = null,
  
         Type = type,
  
         Persist = credPersist
  
       };
  
       var ncred = NativeCredential.GetNativeCredential(cred);
  
       var written = CredWrite(ref ncred, 0);
  
       var lastError = Marshal.GetLastWin32Error();
  
       if (written)
  
       {
  
         return 0;
  
       }
  

  
       var message = "";
  
       if (lastError == 1312)
  
       {
  
         message = (string.Format("Failed to save " + key + " with error code {0}.", lastError)
  
         + "This error typically occurrs on home editions of Windows XP and Vista.Verify the version of Windows is Pro/Business or higher.");
  
       }
  
       else
  
       {
  
         message = string.Format("Failed to save " + key + " with error code {0}.", lastError);
  
       }
  
       MessageBox.Show(message);
  
       return 1;
  
   }
  

  
   /// <summary>
  
   /// 读取凭据
  
   /// </summary>
  
   /// <param name="targetName"></param>
  
   /// <param name="credType"></param>
  
   /// <param name="reservedFlag"></param>
  
   /// <param name="intPtr"></param>
  
   /// <returns></returns>
  
    public static bool WReadCred(string targetName,CRED_TYPE credType,int reservedFlag,out IntPtr intPtr)
  
    {
  
      return CredRead(targetName, CRED_TYPE.DOMAIN_PASSWORD, reservedFlag, out intPtr);
  
    }
  

  
    /// <summary>
  
    /// 删除凭据
  
    /// </summary>
  
    /// <param name="target"></param>
  
    /// <param name="type"></param>
  
    /// <param name="flags"></param>
  
    /// <returns></returns>
  
    public static bool DeleteCred(string target, CRED_TYPE type, int flags)
  
    {
  
      return CredDelete(target, type, flags);
  
    }
  
}
  

  
/// <summary>
  
/// 查询凭据是否存在
  
/// </summary>
  
/// <param name="sender"></param>
  
/// <param name="e"></param>
  
private void btnQuery_Click(object sender, EventArgs e)
  
{
  
    string targetName = txtIP.Text.Trim();
  
    IntPtr intPtr=new IntPtr ();
  
    bool flag = false;
  
    try
  
    {
  
      flag = NativeCredMan.WReadCred(targetName, CRED_TYPE.DOMAIN_PASSWORD, 1, out intPtr);
  
    }
  
    catch{
  
      flag = false;
  
    }
  

  
    if (flag)
  
      txtMsg.Text = "该凭据已存在";
  
    else
  
      txtMsg.Text = "该凭据目前不存在";
  
}
  

  
private void btnDelete_Click(object sender, EventArgs e)
  
{
  
    string targetName = txtIP.Text.Trim();
  
    bool flag = false;
  
    try
  
    {
  
      flag = NativeCredMan.DeleteCred(targetName, CRED_TYPE.DOMAIN_PASSWORD,0);
  
    }
  
    catch
  
    {
  
      flag = false;
  
    }
  

  
    if (flag)
  
      txtMsg.Text = "该凭据已删除";
  
    else
  
      txtMsg.Text = "删除失败";
  
}
页: [1]
查看完整版本: C#代码实现对Windows凭据的管理