2

http基本認証を必要とするASP.NET WebApiサービスがあります(これはデモ用であり、本番用ではないため、基本認証の理由であり、より安全なものではありません)。このサービスは Visual Studio の IIS Express サーバーで正常に動作し、認証はカスタム HTTP モジュールを介して行われます。

ホスティング サーバーにサイトをデプロイすると失敗し、引き続きログイン画面が表示されます。リクエストが送信され、資格情報が送信されていることを Fiddler で確認しました。しかし、401 の不正な応答で応答し続けます。クライアントからサーバーに到達するまでに、要求の資格情報が何らかの形で失われているようです。これを診断するために何時間も費やしましたが、Web API と IIS を使用した .NET 認証は非常に混乱しているようです。助けてください!!

Fiddler からの送信要求は次のように表示されます。

GET mywebsiteaddress HTTP/1.1
Host: 私の Web サイト アドレス
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:21.0) Gecko/20100101 Firefox/21.0
Accept: /
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip、deflate
Authorization: Basic YmJvbm5ldDE4Om9jdG9iZXIxNw==
X-Requested-With: XMLHttpRequest
リファラー: mysite
接続: keep-alive

これが私の構成の関連部分です(必要に応じてさらに投稿できます):

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

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

<authentication mode="Windows"/>

私のカスタム http モジュール (Visual Studio からのテストでも正常に動作します)。これは主に 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 を実行しています。フォーム認証を無効にし、偽装を無効にしました。サーバーで基本認証と匿名認証の方法を有効にしました。

これに関する無数のフォーラムの回答と投稿を読みましたが、明確な答えにつながるものは何もありません.

4

3 に答える 3

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 を手動で設定したり、認証キャッシュを操作したりせずに、ネットワーク資格情報を使用してアプリに接続できます。

于 2018-03-06T08:23:47.490 に答える
0

今日も同じような質問がありました。この問題を解決するための最初のステップは<authentication mode="Windows"/>、Web.config を削除して Windows 認証を無効にすることです。また、応答メッセージはどのようなものですか? WWW-Authenticate で戻ってくるのは何ですか?

于 2013-06-04T03:17:31.133 に答える