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 を実行しています。フォーム認証を無効にし、偽装を無効にしました。サーバーで基本認証と匿名認証の方法を有効にしました。
これに関する無数のフォーラムの回答と投稿を読みましたが、明確な答えにつながるものは何もありません.