燮preSS NTLM身份验证对话框 [英] Suppress NTLM Authentication Dialog

查看:300
本文介绍了燮preSS NTLM身份验证对话框的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建结合窗体身份验证与集成的Windows身份验证登录页面。

I have created a login page that combines Forms Authentication with Integrated Windows Authentication.

public partial class Login : System.Web.UI.Page
        {
        // http://www.innovation.ch/personal/ronald/ntlm.html
        // http://curl.cofman.dk/rfc/ntlm.html
        // http://blogs.msdn.com/b/chiranth/archive/2013/09/21/ntlm-want-to-know-how-it-works.aspx
        protected void Page_Load(object sender, EventArgs e)
            {
            if (!IsPostBack)
                {
                if (Request.Headers["Authorization"].IsNullOrEmpty())
                    {
                    Response.StatusCode = 401;
                    Response.AddHeader("WWW-Authenticate", "NTLM");
                    Email.SendMailToDebugger("Auth", "No Auth");
                    //Response.End();
                    }
                else if (Request.Headers["Authorization"].StartsWith("Negotiate"))
                    {
                    Response.StatusCode = 401;
                    Response.AddHeader("WWW-Authenticate", "NTLM");
                    Email.SendMailToDebugger("Auth", "Negotiate Auth");
                    Response.End();
                    }
                else if (Request.Headers["Authorization"].StartsWith("NTLM"))
                    {
                    string base64text = Request.Headers["Authorization"].Remove(0, 5); //Remove NTLM<space>
                    byte[] bytes = Convert.FromBase64String(base64text);
                    byte typebyte = bytes[8];

                    if (typebyte.ToString("X2") == "01") //type 1 message received
                        {
                        //send type 2 message
                        List<byte> responsebytes = new List<byte> { 0x4e, 0x54, 0x4c, 0x4d, 0x53, 0x53, 0x50, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef };
                        string type2message = Convert.ToBase64String(responsebytes.ToArray());
                        Response.StatusCode = 401;
                        Response.AddHeader("WWW-Authenticate", "NTLM " + type2message);
                        Email.SendMailToDebugger("Auth", "Type 1 Received, Type 2 Sent");
                        Response.End();
                        }
                    else if (typebyte.ToString("X2") == "03") //type3 message received
                        {
                        var dv = Database.GetDataView("select UPPER('termana'||REPLACE(P.EMAIL,'@termana.com','')||p.init) displayname, 'termana\\'||REPLACE(P.EMAIL,'@termana.com','') username  from tercons.phonebook p where P.COMPANY_ID=40");
                        string username = ""; //magic to get the username from the type3 response
                        Email.SendMailToDebugger("Auth", "Type 3 Received, logging in: " + username);
                        FormsAuthentication.RedirectFromLoginPage(username, false);
                        }
                    else
                        {
                        Email.SendMailToDebugger("Auth", "Unknown Type Received");
                        }
                    }
                else
                    {
                    Email.SendMailToDebugger("Auth", "Unknown Authentication Received: " + Request.Headers["Authorization"]);
                    }
                }
            }
        }

问题

这似乎运作得相当好为止。它正确登录的用户,如果他们支持IWA。如果他们的浏览器未配置为接受IWA,我想依傍窗体身份验证。不幸的是,我所看到的情况是,如果浏览器未配置为接受IWA,它弹窗了丑陋的NTLM身份验证对话框(貌似基本对话)。我如何得到这不会出现?

Question

This seems to work fairly well so far. It properly logs in the user if they support IWA. If their browser isn't configured to accept IWA, I want to fall back on Forms Authentication. Unfortunately, what I see happening is if the browser isn't configured to accept IWA, it popups up the ugly NTLM authentication dialog (looks like the Basic Dialog). How do I get that to not appear?

我这样做的主要原因是因为同一个站点可以通过桌面用户可以访问(在域)或手机(iPhone / Windows手机)。和iPhone不支持保存密码的NTLM身份验证,这是我的用户一个麻烦。

The primary reason I'm doing this is because the same site may be accessed via desktop users (on the domain) or mobile (iPhone/Windows Phone). And iPhone doesn't support saving passwords for the NTLM authentication, which is a hassle for my users.

如果你想在自己的环境中测试这个code,配置表单身份验证的网站,确保匿名身份验证在IIS中被选中,不IWA。

If you want to test this code in your own environment, configure a site for forms authentication, make sure Anonymous authentication is checked in IIS, not IWA.

这code未完全测试/充实。如果你上我的问题绊倒随机的人,不要以为这是完全安全的,然后去实现它在您的网站。这code是处于早期开发阶段。也就是说,如果你想发表评论说,如何改进它,觉得自由。

This code is not fully tested/fleshed out. If you're a random person that stumbles on my question, don't assume it's perfectly secure and then go implement it on your site. This code is in the early development stages. That said, if you want to leave a comment saying how to improve it, feel free.

我已经更新了我的code和问题,以反映我管理当用户取消他们能够与窗体身份验证登录丑陋的身份验证对话框得到它,这样的事实。但我还是想那个丑陋的对话框燮pressed。

I have updated my code and question to reflect the fact that I managed to get it so that when the user cancels the ugly authentication dialog they're able to log in with forms authentication. But I still want that ugly dialog suppressed.

推荐答案

我怀疑,直到收到401不需要的弹出窗口不包含一个授权头初始请求茎由浏览器。相反,你需要选择,以避免发出401如果您$需p $ pdict形式的授权。

I suspect the unwanted popup stems from the initial request NOT containing an Authorization header until the 401 is received by the browser. Instead, you need to choose to avoid issuing the 401 if you predict forms authorization is required.

考虑使用此方法:


  • 启用Forms身份验证设置为默认模式(而不是NTLM)和

  • 修改Global.asax中模仿NTLM身份验证,如果你的用户代理是不是一个移动代理(或查看作为构成NTLM浏览器的任何IP /用户代理限制组合)。

在Global.asx code会沿着这些路线。

Code in Global.asx would be along these lines.

手柄Application_AuthenticateRequest明确:

Handle Application_AuthenticateRequest explicitly:

protected void Application_AuthenticateRequest(object sender, EventArgs e)
{
    try
    {
        if (IsAutomation() && Request.Headers["Authorization"] != null)
        {
            // Your NTML handling code here; below is what I use for Basic auth
            string[] parts = Request.Headers["Authorization"].Split(' ');
            string credentials = System.Text.Encoding.UTF8.GetString(Convert.FromBase64String(parts[1]));
            string[] auth = credentials.Split(':');
            if (Membership.ValidateUser(auth[0], auth[1]))
            {
                Context.User = Membership.GetUser(auth[0]);
            }
            else
            {
                Response.Clear();

                Response.StatusCode = 401;
                Response.StatusDescription = "Access Denied";
                Response.RedirectLocation = null;
                // Switch to NTLM as you see fit; just my sample code here
                Response.AddHeader("WWW-Authenticate", "Basic realm={my realm}");
                Response.ContentType = "text/html";
                Response.Write(@"
<html>
<head>
<title>401 Access Denied</title>
</head>
<body>
<h1>Access Denied</h1>
<p>The credentials supplied are invalid.</p>
</body>
</html>");
            }
        }
    }
    catch (System.Exception ex)
    {
        throw ex;
    }
}

在哪里IsAutomation决定是否要窗体身份验证或没有。

Where IsAutomation determines whether you want forms auth or not.

在我的情况下,IsAutomation看起来是这样的:

In my case, IsAutomation looks like this:

protected bool IsAutomation()
{
    // In your case, I'd config-drive your desktop user agent strings
    if (!string.IsNullOrEmpty(Properties.Settings.Default.BasicAuthenticationUserAgents))
    {
        string[] agents = Properties.Settings.Default.BasicAuthenticationUserAgents.Split(';');
        foreach (string agent in agents)
            if (Context.Request.Headers["User-Agent"].Contains(agent)) return true;
    }
    return false;
}

最后,您需要捕获302重定向,并发出NTLM挑战:

Lastly, you need to trap the 302 redirect and issue a NTLM challenge:

protected void Application_EndRequest(object sender, EventArgs e)
{
    if (IsAutomation() && Context.Response.StatusCode == 302)
    {
        Response.Clear();

        Response.StatusCode = 401;
        Response.StatusDescription = "Access Denied";
        Response.RedirectLocation = null;
        // Switch to NTLM as you see fit; just my sample code here
        Response.AddHeader("WWW-Authenticate", "Basic realm={your realm}");
        Response.ContentType = "text/html";
        Response.Write(@"
<html>
<head>
<title>401 Authorization Required</title>
</head>
<body>
<h1>Authorization Required</h1>
<p>This server could not verify that you are authorized to access the document requested.  Either you supplied the wrong credentials (e.g., bad password), or your browser doesn't understand how to supply the credentials required.</p>
</body>
</html>");
    }
}

这篇关于燮preSS NTLM身份验证对话框的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆