Suppress NTLM Authentication Dialog

不打扰是莪最后的温柔 提交于 2019-12-01 01:04:52

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.

Consider this approach:

  • Enable Forms authentication as the default mode (not NTLM), and
  • Modify Global.asax to mimic the NTLM authentication if your user agent is not a mobile agent (or whatever combination of IP/user agent restriction you view as constituting NTLM browsers).

Code in Global.asx would be along these lines.

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;
    }
}

Where IsAutomation determines whether you want forms auth or not.

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;
}

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>");
    }
}

I think you're getting confused between the concepts of NTLM/IWA authentication, and the niceties of having a browser automatically log you in for a trusted site. If I was to rephrase this question, you're actually asking if the server can detect if a browser will automatically log someone in without asking for credentials using IWA, before you offer IWA as a method of authentication. The answer to this is a resounding "no." The zones and the security settings which control this behaviour are entirely on the user's machine.

Now, if you're in an intranet environment and you can recognize certain IP address ranges as belonging to machines that you already know will perform automatic IWA, then sure, that works. It sounds to me like you're trying to generalize, and for that, you cannot make this work.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!