![](/img/trans.png)
[英]Web API Getting 401 Unauthorized in IIS but works in IIS Express
[英]Getting IIS unauthorized html page instead of web api unauthorized response for unauthorized status
我在IIS 10(Windows Server 2016)上托管了一個Web API應用程序。 該應用程序具有登錄API。 登錄API使用實現IAuthenticationFilter的自定義身份驗證過濾器屬性進行修飾。
[RoutePrefix("api/login")]
[AllowUnAuthorized]
[AuthenticationFilter]
public class LoginController : ApiController
{
[HttpPost]
public IHttpActionResult Login()
{
//Code to return token if passed authentication in the Authentication Filter
}
}
如果登錄憑據(UserName和Password)無效,則Authentication Filter屬性會在上下文中設置ErrorResult,並返回狀態代碼為401(“Unauthorized”)並帶有響應消息。
public class AuthenticationFilter : Attribute, IAuthenticationFilter
{
public bool AllowMultiple => false;
public async Task AuthenticateAsync(HttpAuthenticationContext context,
CancellationToken cancellationToken)
{
HttpRequestMessage request = context.Request;
AuthenticationHeaderValue authorization =
request.Headers.Authorization;
if (authorization == null)
{
return;
}
if (authorization.Scheme != "Basic")
{
return;
}
Tuple<string, string> credentials =
ExtractCredentials(request.Headers);
if (credentials == null)
{
context.ErrorResult = new AuthenticationFailureResult("Invalid
credentials", request);
return;
}
string userName = credentials.Item1;
string password = credentials.Item2;
IAuthenticationService
service=container.Resolve<IAuthenticationService>();
var user = service.GetUser(userName, password);
if (user == null)
{
context.ErrorResult = new AuthenticationFailureResult("Invalid username or password", request);
return;
}
//Code to set principal if authentication passed
}
這是AuthenticationFailureResult類的代碼。
internal class AuthenticationFailureResult : IHttpActionResult
{
public string ReasonPhrase { get; private set; }
public HttpRequestMessage Request { get; private set; }
public AuthenticationFailureResult(string reasonPhrase, HttpRequestMessage request)
{
ReasonPhrase = reasonPhrase;
Request = request;
}
public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
{
return Task.FromResult(Execute());
}
private HttpResponseMessage Execute()
{
HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.Unauthorized);
response.RequestMessage = Request;
response.ReasonPhrase = ReasonPhrase;
return response;
}
}
此代碼工作正常,並返回401狀態代碼以及原因短語中指定的消息。 但是我不知道由於什么變化,突然API返回一個html頁面,該頁面通常由IIS返回,消息“401 - 未經授權:由於憑證無效而拒絕訪問”。 而不是在身份驗證過濾器中設置的錯誤響應。 請注意,在IISExpress中運行時,相同的API可以正常工作
到目前為止我做了什么:
在Web.config中添加了以下內容
<system.webServer> <modules runAllManagedModulesForAllRequests="true"/> </system.webServer>
奇怪的是,當驗證通過時,web api會返回正確的JSON響應
編輯1:
這是ChallengeAsync方法
public Task ChallengeAsync(HttpAuthenticationChallengeContext context, CancellationToken cancellationToken)
{
var challenge = new AuthenticationHeaderValue("Basic");
context.Result = new AddChallengeOnUnauthorizedResult(challenge, context.Result);
return Task.FromResult(0);
}
AddChallengeOnUnauthorizedResult的實現
public class AddChallengeOnUnauthorizedResult : IHttpActionResult
{
public AddChallengeOnUnauthorizedResult(AuthenticationHeaderValue challenge, IHttpActionResult innerResult)
{
Challenge = challenge;
InnerResult = innerResult;
}
public AuthenticationHeaderValue Challenge { get; private set; }
public IHttpActionResult InnerResult { get; private set; }
public async Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
{
HttpResponseMessage response = await InnerResult.ExecuteAsync(cancellationToken);
if (response.StatusCode == HttpStatusCode.Unauthorized)
{
// Only add one challenge per authentication scheme.
if (!response.Headers.WwwAuthenticate.Any((h) => h.Scheme == Challenge.Scheme))
{
response.Headers.WwwAuthenticate.Add(Challenge);
}
}
return response;
}
}
解決方案是在Web.config中添加以下兩個設置。
<system.webServer>
<httpErrors existingResponse="PassThrough" />
<modules runAllManagedModulesForAllRequests="true" />
</system.webServer>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.