簡體   English   中英

獲取IIS未經授權的html頁面而不是web api未經授權的響應未授權狀態

[英]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可以正常工作

到目前為止我做了什么:

  1. 檢查Web.config並驗證CustomErrors Mode設置為“On”
  2. 確保在IIS中的站點的“身份驗證”部分中啟用了“匿名身份驗證”
  3. 在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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM