【发布时间】: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