Windows安全自定义登录验证自定义、安全、Windows

2023-09-03 07:29:02 作者:旅人与风

我创建的XAML / C#应用程序,我想它弹出一个登录提示。

我想知道,如果它可能使用CredUIPromptForWindowsCredentials。

显示Windows安全对话框 获取输入的用户名和放大器;密码 执行自定义验证 如果验证更迭 - >继续应用 否则,如果验证失败 - >无效的用户名或密码的-inform用户

我已经看了 Windows安全登录表单?和的http://www.pinvoke.net/default.aspx/credui/creduipromptforwindowscredentials.html?diff=y但他们没有说明如何处理验证。

我会很喜欢的一个小例子,在那里,如果用户输入的用户名=博和密码=123,然后更迭否则显示错误信息,并允许用户再试一次。

应用程序将被多台计算机上安装。

或者,这是根本不可能的?

更新

在这个问题的答案Show在C#中使用Windows身份验证对话框Vista / 7的

我已经修改了code到正常工作。

请不,该验证部分仅用于概念验证。

WindowsSecurityDialog.cs

 公共类WindowsSecurityDialog
    {

       公共字符串CaptionText {获得;组; }
       公共字符串{的MessageText获得;组; }

        [的DllImport(OLE32.DLL)
        公共静态外部无效CoTaskMemFree(IntPtr的PTR);

        [StructLayout(LayoutKind.Sequential,字符集= CharSet.Auto)
        私人结构CREDUI_INFO
        {
            公众诠释CBSIZE;
            公众的IntPtr hwndParent;
            公共字符串pszMessageText;
            公共字符串pszCaptionText;
            公众的IntPtr hbmBanner;
        }


        [的DllImport(credui.dll,字符集= CharSet.Auto)
        私人静态外部布尔CredUnPackAuthenticationBuffer(INT dwFlags中,
                                                                   IntPtr的pAuthBuffer,
                                                                   UINT cbAuthBuffer,
                                                                   StringBuilder的pszUserName,
                                                                   REF INT pcchMaxUserName,
                                                                   StringBuilder的pszDomainName,
                                                                   REF INT pcchMaxDomainame,
                                                                   StringBuilder的pszPassword,
                                                                   REF INT pcchMaxPassword);

        [的DllImport(credui.dll,字符集= CharSet.Auto)
        私人静态外部INT CredUIPromptForWindowsCredentials(REF CREDUI_INFO notUsedHere,
                                                                     INT authError,
                                                                     裁判UINT authPackage,
                                                                     IntPtr的InAuthBuffer,
                                                                     UINT InAuthBufferSize,
                                                                     出的IntPtr refOutAuthBuffer,
                                                                     出UINT refOutAuthBufferSize,
                                                                     裁判布尔FSAVE,
                                                                     诠释标志);



        公共BOOL的ValidateUser()
        {
            VAR credui =新CREDUI_INFO
                                     {
                                         pszCaptionText = CaptionText,
                                         pszMessageText =的MessageText
                                     };
            credui.cbSize = Marshal.SizeOf(credui);
            UINT authPackage = 0;
            IntPtr的outCredBuffer;
            UINT outCredSize;
            布尔省= FALSE;


            const int的loginError code = 1326; //登录失败
            变种authError = 0;

            而(真)
            {




                VAR的结果= CredUIPromptForWindowsCredentials(REF credui,
                                                               authError,
                                                               REF authPackage,
                                                               IntPtr.Zero,
                                                               0,
                                                               出outCredBuffer,
                                                               出outCredSize,
                                                               REF保存,
                                                               1 / *通用* /);

                VAR usernameBuf =新的StringBuilder(100);
                VAR passwordBuf =新的StringBuilder(100);
                VAR domainBuf =新的StringBuilder(100);

                VAR maxUserName = 100;
                VAR maxDomain = 100;
                VAR maxPassword = 100;
                如果(结果== 0)
                {
                    如果(CredUnPackAuthenticationBuffer(0,outCredBuffer,outCredSize,usernameBuf,裁判maxUserName,
                                                       domainBuf,裁判maxDomain,passwordBuf,裁判maxPassword))
                    {
                        // TODO:MS文档说,我们应该把这个,但我不能让它开始工作
                        // SecureZeroMem(outCredBuffer,outCredSize);

                        //清除由CredUIPromptForWindowsCredentials分配的内存
                        CoTaskMemFree(outCredBuffer);
                        VAR的NetworkCredential =新的NetworkCredential()
                                                {
                                                    用户名= usernameBuf.ToString(),
                                                    密码= passwordBuf.ToString(),
                                                    域= domainBuf.ToString()
                                                };

                        //假code请用真实的用户验证
                        如果(networkCredential.UserName ==博与功放;&安培; networkCredential.Password ==1234)
                            返回true;
                        否则//注册与登录错误再次失败显示对话框
                        {
                            authError = loginError code;
                        }



                    }
                }
                否则返回false;


            }
        }
    }
 
windows7安全设置怎么进入

App.xaml.cs

 保护覆盖无效OnStartup(StartupEventArgs E)
        {
            VAR windowsSecurityDialog =新WindowsSecurityDialog
                                            {
                                                CaptionText =请输入您的凭据
                                                =的MessageText这些凭证将用于连接到您的应用程序的名称;
                                            };

            如果(windowsSecurityDialog.ValidateUser())
                base.OnStartup(E);
        }
 

解决方案

您会发现一个完全实现WPF和使用CredUIPromptForWindowsCredentials在的 Ookii对话框的。

I'm creating an Xaml/C# application and I would like it to popup with a Login Prompt.

I would like to know if its possible to use CredUIPromptForWindowsCredentials.

Show Windows Security Dialog Get the entered username & password Perform Custom validation If validation succes -> continue app else if validation failed -> -inform user of invalid username or password

I have already looked at Windows Security login form? and http://www.pinvoke.net/default.aspx/credui/creduipromptforwindowscredentials.html?diff=y but they don't explain how to handle the validation.

I would really like a small example, where if the user enters username = "Bo" and password = "123" then succes else display error message and allow the user to try again.

The App is going to be installed on multiple computers.

Or is this simply not possible?

Update

Inspired by the answer in this question Show Authentication dialog in C# for windows Vista/7

I have modified the code to work as expected.

Please not, that the validation part is only for proof of concept.

WindowsSecurityDialog.cs

 public class WindowsSecurityDialog
    {

       public string CaptionText { get; set; }
       public string MessageText { get; set; }

        [DllImport("ole32.dll")]
        public static extern void CoTaskMemFree(IntPtr ptr);

        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
        private struct CREDUI_INFO
        {
            public int cbSize;
            public IntPtr hwndParent;
            public string pszMessageText;
            public string pszCaptionText;
            public IntPtr hbmBanner;
        }


        [DllImport("credui.dll", CharSet = CharSet.Auto)]
        private static extern bool CredUnPackAuthenticationBuffer(int dwFlags,
                                                                   IntPtr pAuthBuffer,
                                                                   uint cbAuthBuffer,
                                                                   StringBuilder pszUserName,
                                                                   ref int pcchMaxUserName,
                                                                   StringBuilder pszDomainName,
                                                                   ref int pcchMaxDomainame,
                                                                   StringBuilder pszPassword,
                                                                   ref int pcchMaxPassword);

        [DllImport("credui.dll", CharSet = CharSet.Auto)]
        private static extern int CredUIPromptForWindowsCredentials(ref CREDUI_INFO notUsedHere,
                                                                     int authError,
                                                                     ref uint authPackage,
                                                                     IntPtr InAuthBuffer,
                                                                     uint InAuthBufferSize,
                                                                     out IntPtr refOutAuthBuffer,
                                                                     out uint refOutAuthBufferSize,
                                                                     ref bool fSave,
                                                                     int flags);



        public bool ValidateUser()
        {
            var credui = new CREDUI_INFO
                                     {
                                         pszCaptionText = CaptionText,
                                         pszMessageText = MessageText
                                     };
            credui.cbSize = Marshal.SizeOf(credui);
            uint authPackage = 0;
            IntPtr outCredBuffer;
            uint outCredSize;
            bool save = false;


            const int loginErrorCode = 1326;    //Login Failed
            var authError = 0;

            while (true)
            {




                var result = CredUIPromptForWindowsCredentials(ref credui,
                                                               authError,
                                                               ref authPackage,
                                                               IntPtr.Zero,
                                                               0,
                                                               out outCredBuffer,
                                                               out outCredSize,
                                                               ref save,
                                                               1 /* Generic */);

                var usernameBuf = new StringBuilder(100);
                var passwordBuf = new StringBuilder(100);
                var domainBuf = new StringBuilder(100);

                var maxUserName = 100;
                var maxDomain = 100;
                var maxPassword = 100;
                if (result == 0)
                {
                    if (CredUnPackAuthenticationBuffer(0, outCredBuffer, outCredSize, usernameBuf, ref maxUserName,
                                                       domainBuf, ref maxDomain, passwordBuf, ref maxPassword))
                    {
                        //TODO: ms documentation says we should call this but i can't get it to work
                        //SecureZeroMem(outCredBuffer, outCredSize);

                        //clear the memory allocated by CredUIPromptForWindowsCredentials 
                        CoTaskMemFree(outCredBuffer);
                        var networkCredential = new NetworkCredential()
                                                {
                                                    UserName = usernameBuf.ToString(),
                                                    Password = passwordBuf.ToString(),
                                                    Domain = domainBuf.ToString()
                                                };

                        //Dummy Code replace with true User Validation
                        if (networkCredential.UserName == "Bo" && networkCredential.Password == "1234")
                            return true;
                        else //login failed show dialog again with login error
                        {
                            authError = loginErrorCode;
                        }



                    }
                }
                else return false;


            }
        }
    }

App.xaml.cs

protected override void OnStartup(StartupEventArgs e)
        {
            var windowsSecurityDialog = new WindowsSecurityDialog
                                            {
                                                CaptionText = "Enter your credentials",
                                                MessageText = "These credentials will be used to connect to YOUR APP NAME";
                                            };

            if (windowsSecurityDialog.ValidateUser())
                base.OnStartup(e);
        }

解决方案

You'll find a complete implementation for WPF and WinForms using CredUIPromptForWindowsCredentials at Ookii dialogs.