【问题标题】:unable to authenticate using basic authentication无法使用基本身份验证进行身份验证
【发布时间】:2013-05-30 03:34:56
【问题描述】:

我有一个需要 http 基本身份验证的 ASP.NET WebApi 服务(这是用于演示,而不是用于生产,所以这是基本身份验证的原因,而不是更安全的东西)。该服务在 Visual Studio IIS Express 服务器上运行良好,身份验证通过自定义 HTTP 模块进行。

当我将站点部署到托管服务器时,它失败并继续弹出登录屏幕。我与 Fiddler 确认正在发送请求并且正在发送凭据。但它一直以 401 未经授权的响应进行响应。在从客户端到服务器的过程中,请求凭据似乎以某种方式丢失了。我花了很多很多时间试图诊断这个问题,而使用 Web API 和 IIS 的 .NET 身份验证似乎很混乱。请帮忙!!

来自 Fiddler 的传出请求显示:

获取我的网站地址 HTTP/1.1
主持人:我的网址
用户代理:Mozilla/5.0 (Windows NT 6.1; WOW64; rv:21.0) Gecko/20100101 Firefox/21.0
接受:/
接受语言:en-US,en;q=0.5
接受编码:gzip、deflate
授权:基本 YmJvbm5ldDE4Om9jdG9iZXIxNw==
X-Requested-With: XMLHttpRequest
推荐人:我的网站
连接:保持活动

以下是我的配置的相关部分(如有必要,我可以发布更多内容):

<modules>
  <add name="BasicAuthHttpModule" type="ITMService.Modules.BasicAuthHttpModule"/>
</modules>

<httpModules>
  <add name="BasicAuthHttpModule" type="ITMService.Modules.BasicAuthHttpModule"/>
</httpModules>

<authentication mode="Windows"/>

我的自定义 http 模块(在 Visual Studio 的测试中也可以正常工作)。这主要取自example on asp.net

namespace ITMService.Modules
{
public class BasicAuthHttpModule : IHttpModule
{

    private const string Realm = "www.mysite.net";

    public void Init(HttpApplication context)
    {
        context.AuthenticateRequest += OnApplicationAuthenticateRequest;
        context.EndRequest += OnApplicationEndRequest;

    }

    private static void SetPrincipal(IPrincipal principal)
    {
        Thread.CurrentPrincipal = principal;
        if (HttpContext.Current != null)
        {
            HttpContext.Current.User = principal;
            Log.LogIt("current principal: " + principal.Identity.Name);
        }
    }


    private static bool CheckPassword(string username, string password)
    {
        string passHash = AuthUser.GetUserPassword(username);
        if (PasswordHash.ValidatePassword(password, passHash))
        {
            return true;
        }
        else
        {
            return false;
        }

    }

    private static bool AuthenticateUser(string credentials)
    {
        bool validated = false;

        try
        {
            var encoding = Encoding.GetEncoding("iso-8859-1");
            credentials = encoding.GetString(Convert.FromBase64String(credentials));

            int separator = credentials.IndexOf(':');
            string name = credentials.Substring(0, separator);
            string password = credentials.Substring(separator + 1);

            validated = CheckPassword(name, password);

            if (validated)
            {
                var identity = new GenericIdentity(name);
                SetPrincipal(new GenericPrincipal(identity, null));
            }
        }
        catch (FormatException)
        {
            // Credentials were not formatted correctly.
            validated = false;
            Log.LogIt("not validated");

        }
        return validated;
    }

    private static void OnApplicationAuthenticateRequest(object sender, EventArgs e)
    {

        var request = HttpContext.Current.Request;
        var authHeader = request.Headers["Authorization"];
        if (authHeader != null)
        {

            var authHeaderVal = AuthenticationHeaderValue.Parse(authHeader);

            // RFC 2617 sec 1.2, "scheme" name is case-insensitive
            if (authHeaderVal.Scheme.Equals("basic",
                    StringComparison.OrdinalIgnoreCase) &&
                authHeaderVal.Parameter != null)
            {

                AuthenticateUser(authHeaderVal.Parameter);
            }
        }
    }

    // If the request was unauthorized, add the WWW-Authenticate header 
    // to the response.
    private static void OnApplicationEndRequest(object sender, EventArgs e)
    {

        var response = HttpContext.Current.Response;
        if (response.StatusCode == 401)
        {
            response.Headers.Add("WWW-Authenticate",
                string.Format("Basic realm=\"{0}\"", Realm));
        }
    }

    public void Dispose()
    {
    }
}
}

我的 IIS 服务器在集成管道模式下托管并运行 .NET 4。我禁用了表单身份验证和禁用模拟。我在服务器上启用了基本身份验证和匿名身份验证方法。

我已经阅读了无数关于此问题的论坛回复和帖子,但没有任何东西可以让我得到明确的答案。

【问题讨论】:

  • 您可能希望使用 https 进行基本身份验证。
  • 我确实计划使用 https,但我想从一开始就进行身份验证,但这是一个很好的观点,我肯定会这样做。
  • 仅供参考,您刚刚暴露了您的凭据,用户 bbonnet18 通过 october17。

标签: .net authentication iis asp.net-web-api httpmodule


【解决方案1】:

只是为了完整性:

BasicAuthentication 的大多数示例都描述了在 IIS 应用程序配置中启用“Windows 身份验证”。这在许多情况下都有效(例如连接到站点的浏览器),但不适用于使用网络凭据的 dotNet 客户端。为什么会这样?

通过提琴手的简要介绍给了我以下 http 标头:

WWW-Authenticate: Basic realm="My Realm"
WWW-Authenticate: Negotiate
WWW-Authenticate: NTLM

浏览器正在选择 BasicAuthentication。但是 dotClient 正在启动协商 (Kerberos) 或 NTLM 身份验证。

案例 1:如果您的服务器在同一个域中并且您使用的是正常的登录凭据 => 一切正常,服务器正在为您进行协商

案例 2:如果您的 webapp 提供了自己的 BasicAuthenticationModule 进行身份验证(例如,有自己的用户数据库),则身份验证失败。

案例 2 的解决方案: 在 iis 或 system.webServer-security 中禁用 Windows 身份验证,以便仅向客户端提供 BasicAuthentication。然后您可以使用网络凭据连接到应用程序,而无需手动设置 AuthenticationHeader 或操作身份验证缓存。

【讨论】:

    【解决方案2】:

    我看到两个 www-Authenticate 响应标头。我相信您的 HTTP 模块正在添加一个,而 IIS 正在添加一个。确保在 IIS 中禁用各种身份验证,就像这样。我的猜测是您在 IIS 中启用了基本身份验证。

    【讨论】:

    • 非常感谢您的帮助。将它们全部禁用实际上不会停止将请求路由到我的自定义模块吗?还是现在将其传递给不同级别的自定义模块?
    • 您的模块应该可以正常运行。禁用它们,看看它是否适合你。如果可行,请接受我的答案作为答案。这是人们在 StackOverflow 中所做的事情,顺便说一句。
    • 我理解答案的事情,如果它有效,我肯定会接受 - 我要到今天晚些时候才能测试。
    • 我的托管服务提供商锁定了基本身份验证,因此我无法禁用它。我有一张票可以更改它,但不确定何时或是否会为我禁用它。如果您有任何其他想法,请告诉我(也许可以找到不同的托管服务提供商!)。谢谢你的回答。
    • 您可以将其添加到您的 web.config 中。 ....
    【解决方案3】:

    今天还有另一个question 也是如此。解决此问题的第一步是通过在 Web.config 中删除 &lt;authentication mode="Windows"/&gt; 来禁用 Windows 身份验证。另外,响应消息是什么样的? WWW-Authenticate 中返回了什么?

    【讨论】:

    • 是的,这是一个身份验证响应 - fiddler 中的响应是这样的:HTTP/1.1 401 Unauthorized Content-Type: text/html Server: Microsoft-IIS/7.5 WWW-Authenticate: Basic realm="www .itmmobile.net" WWW-Authenticate: Basic realm="www.itmmobile.net" X-Powered-By: ASP.NET Date: Tue, 04 Jun 2013 04:31:04 GMT Content-Length: 1293
    猜你喜欢
    • 2017-06-13
    • 2015-08-12
    • 2016-07-01
    • 2017-09-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-15
    • 1970-01-01
    相关资源
    最近更新 更多