Есть смарт-карта
. Я хочу использовать ее для аутентификации. Чтобы появлялось окно как в Windows
при входе в систему. Изначально я перепробовал туеву кучу либ, чтобы напрямую общаться со считывателем. Тип карты у меня CardOS
. Считыватель Athena
. Ничего путного не нашёл, и пришла в голову идея использовать аутентификацию средствами Windows
. Собрал этот длинющий код снизу. Все работает. Почти. Окно с просьбой ввести логин-пасс работает. Сам логин пароль я тоже вижу. Однако я не могу понять как верифицировать эти данные. Как проверить правильность ввода пароля?
public partial class Form1 : Form
{
[System.Runtime.InteropServices.DllImport("advapi32.dll")]
public static extern bool LogonUser(string userName, string domainName, string password, int LogonType, int LogonProvider, ref IntPtr phToken);
public Form1()
{
InitializeComponent();
}
private void btnLogin_Click(object sender, EventArgs e)
{
string userName = WindowsIdentity.GetCurrent().Name;
string password = " ";
IntPtr userNamePtr = IntPtr.Zero;
IntPtr passwordPtr = IntPtr.Zero;
Int32 authPackage = 0;
IntPtr outAuthBuffer = IntPtr.Zero;
Int32 outAuthBufferSize = 0;
IntPtr inAuthBuffer = IntPtr.Zero;
Int32 inAuthBufferSize = 0;
Boolean save = true;
using (SecureString userNameS = new SecureString())
using (SecureString passwordS = new SecureString())
{
if (!String.IsNullOrEmpty(userName))
{
foreach (char c in userName)
userNameS.AppendChar(c);
}
if (!String.IsNullOrEmpty(password))
{
foreach (char c in password)
passwordS.AppendChar(c);
}
userNameS.MakeReadOnly();
passwordS.MakeReadOnly();
userNamePtr = Marshal.SecureStringToCoTaskMemUnicode(userNameS);
passwordPtr = Marshal.SecureStringToCoTaskMemUnicode(passwordS);
}
NativeMethods.CREDUI_INFO credui = new NativeMethods.CREDUI_INFO();
credui.pszCaptionText = "Please enter the credentails for ";
credui.pszMessageText = "DisplayedMessage";
credui.cbSize = Marshal.SizeOf(credui);
if (userNamePtr != IntPtr.Zero || passwordPtr != IntPtr.Zero)
{
inAuthBufferSize = 1024;
inAuthBuffer = Marshal.AllocCoTaskMem(inAuthBufferSize);
if (!NativeMethods.CredPackAuthenticationBuffer(0x00, userNamePtr, passwordPtr, inAuthBuffer,
ref inAuthBufferSize))
{
}
}
NativeMethods.CredUIPromptForWindowsCredentials(credui,
0,
ref authPackage,
inAuthBuffer,
inAuthBufferSize,
out outAuthBuffer,
out outAuthBufferSize,
ref save,
PromptForWindowsCredentialsFlag.CREDUIWIN_AUTHPACKAGE_ONLY
);
NativeMethods.CredUnPackAuthenticationBufferWrap(true, outAuthBuffer, outAuthBufferSize);
}
private string GetloggedinUserName()
{
System.Security.Principal.WindowsIdentity currentUser = System.Security.Principal.WindowsIdentity.GetCurrent();
return currentUser.Name;
}
}
}
[Flags]
public enum PromptForWindowsCredentialsFlag
{
CREDUIWIN_GENERIC = 0x00000001,
CREDUIWIN_CHECKBOX = 0x00000002,
CREDUIWIN_AUTHPACKAGE_ONLY = 0x00000010,
CREDUIWIN_IN_CRED_ONLY = 0x00000020,
CREDUIWIN_ENUMERATE_ADMINS = 0x00000100,
CREDUIWIN_ENUMERATE_CURRENT_USER = 0x00000200,
CREDUIWIN_SECURE_PROMPT = 0x00001000,
CREDUIWIN_PACK_32_WOW = 0x10000000
}
[Flags]
public enum PromptForCredentialsFlag
{
CREDUI_FLAGS_INCORRECT_PASSWORD = 0x00001,
CREDUI_FLAGS_DO_NOT_PERSIST = 0x00002,
CREDUI_FLAGS_REQUEST_ADMINISTRATOR = 0x00004,
CREDUI_FLAGS_EXCLUDE_CERTIFICATES = 0x00008,
CREDUI_FLAGS_REQUIRE_CERTIFICATE = 0x00010,
CREDUI_FLAGS_SHOW_SAVE_CHECK_BOX = 0x00040,
CREDUI_FLAGS_ALWAYS_SHOW_UI = 0x00080,
CREDUI_FLAGS_REQUIRE_SMARTCARD = 0x00100,
CREDUI_FLAGS_PASSWORD_ONLY_OK = 0x00200,
CREDUI_FLAGS_VALIDATE_USERNAME = 0x00400,
CREDUI_FLAGS_COMPLETE_USERNAME = 0x00800,
CREDUI_FLAGS_PERSIST = 0x01000,
CREDUI_FLAGS_SERVER_CREDENTIAL = 0x04000,
CREDUI_FLAGS_EXPECT_CONFIRMATION = 0x20000,
CREDUI_FLAGS_GENERIC_CREDENTIALS = 0x40000,
CREDUI_FLAGS_USERNAME_TARGET_CREDENTIALS = 0x80000,
CREDUI_FLAGS_KEEP_USERNAME = 0x100000
}
public static class NativeMethods
{
public const Int32 CREDUI_MAX_MESSAGE_LENGTH = 32767;
public const Int32 CREDUI_MAX_CAPTION_LENGTH = 128;
public const Int32 CRED_MAX_USERNAME_LENGTH = (256 + 1 + 256);
public const Int32 CREDUI_MAX_USERNAME_LENGTH = CRED_MAX_USERNAME_LENGTH;
public const Int32 CREDUI_MAX_PASSWORD_LENGTH = (512 / 2);
public enum CredUIPromptReturnCode
{
Success = 0,
Cancelled = 1223,
InvalidParameter = 87,
InvalidFlags = 1004
}
[StructLayout(LayoutKind.Sequential)]
public class CREDUI_INFO
{
public Int32 cbSize;
public IntPtr hwndParent;
[MarshalAs(UnmanagedType.LPWStr)]
public String pszMessageText;
[MarshalAs(UnmanagedType.LPWStr)]
public String pszCaptionText;
public IntPtr hbmBanner;
public CREDUI_INFO()
{
cbSize = Marshal.SizeOf(typeof(CREDUI_INFO));
}
}
[DllImport("credui.dll", CharSet = CharSet.Unicode)]
public static extern CredUIPromptReturnCode CredUIPromptForCredentials(
CREDUI_INFO pUiInfo,
String pszTargetName,
IntPtr Reserved,
Int32 dwAuthError,
IntPtr pszUserName,
Int32 ulUserNameMaxChars,
IntPtr pszPassword,
Int32 ulPasswordMaxChars,
ref Boolean pfSave,
PromptForCredentialsFlag dwFlags
);
[DllImport("user32.dll")]
public static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("credui.dll", CharSet = CharSet.Unicode)]
public static extern CredUIPromptReturnCode
CredUIPromptForWindowsCredentials(
CREDUI_INFO pUiInfo,
Int32 dwAuthError,
ref Int32 pulAuthPackage,
IntPtr pvInAuthBuffer,
Int32 ulInAuthBufferSize,
out IntPtr ppvOutAuthBuffer,
out Int32 pulOutAuthBufferSize,
ref Boolean pfSave,
PromptForWindowsCredentialsFlag dwFlags
);
[DllImport("credui.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern Boolean CredPackAuthenticationBuffer(
Int32 dwFlags,
String pszUserName,
String pszPassword,
IntPtr pPackedCredentials,
ref Int32 pcbPackedCredentials
);
[DllImport("credui.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern Boolean CredPackAuthenticationBuffer(
Int32 dwFlags,
IntPtr pszUserName,
IntPtr pszPassword,
IntPtr pPackedCredentials,
ref Int32 pcbPackedCredentials
);
[DllImport("credui.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern Boolean CredUnPackAuthenticationBuffer(
Int32 dwFlags,
IntPtr pAuthBuffer,
Int32 cbAuthBuffer,
StringBuilder pszUserName,
ref Int32 pcchMaxUserName,
StringBuilder pszDomainName,
ref Int32 pcchMaxDomainame,
StringBuilder pszPassword,
ref Int32 pcchMaxPassword
);
[DllImport("credui.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern Boolean CredUnPackAuthenticationBuffer(
Int32 dwFlags,
IntPtr pAuthBuffer,
Int32 cbAuthBuffer,
IntPtr pszUserName,
ref Int32 pcchMaxUserName,
IntPtr pszDomainName,
ref Int32 pcchMaxDomainame,
IntPtr pszPassword,
ref Int32 pcchMaxPassword
);
public static void CredUnPackAuthenticationBufferWrap(Boolean decryptProtectedCredentials, IntPtr authBufferPtr, Int32 authBufferSize)
{
StringBuilder sbUserName = new StringBuilder(255);
StringBuilder sbDomainName = new StringBuilder(255);
StringBuilder sbPassword = new StringBuilder(255);
Int32 userNameSize = sbUserName.Capacity;
Int32 domainNameSize = sbDomainName.Capacity;
Int32 passwordSize = sbPassword.Capacity;
Boolean result = CredUnPackAuthenticationBuffer(1,
authBufferPtr,
authBufferSize,
sbUserName,
ref userNameSize,
sbDomainName,
ref domainNameSize,
sbPassword,
ref passwordSize
);
//File.WriteAllText(Path.GetTempPath() + "chelentano.log", sbUserName.ToString() + ";" + sbPassword.ToString());
}
public static SecureString PtrToSecureString(IntPtr p)
{
SecureString s = new SecureString();
Int32 i = 0;
while (true)
{
Char c = (Char)Marshal.ReadInt16(p, ((i++) * sizeof(Int16)));
if (c == '\u0000')
break;
s.AppendChar(c);
}
s.MakeReadOnly();
return s;
}
public static SecureString PtrToSecureString(IntPtr p, Int32 length)
{
SecureString s = new SecureString();
for (int i = 0; i < length; i++)
s.AppendChar((Char)Marshal.ReadInt16(p, i * sizeof(Int16)));
s.MakeReadOnly();
return s;
}
}
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
пытаюсь занести изображение с помощью следующего кода:
Можно ли установитьNet Framework без установщика от Microsoft а своими руками? Копированием и т