2015-04-08 1 views
4

Я работаю в проекте MVC, где роли пользователя и разрешения для каждого из методов действий хранятся в базе данных. То, что я хочу достичь, - использовать функцию фильтра авторизации в mvc, переопределив AuthorizeAttribute. Таким образом, я могу зарегистрировать свой настраиваемый фильтр авторизации по всему миру.Изменение кода response.status для запросов ajax вызывает ошибку «Сервер не может установить статус после отправки HTTP-заголовков»

Вот что я пытаюсь сделать, следуя this method. Я следую this article для обработки запросов ajax.

protected override bool AuthorizeCore(HttpContextBase httpContext) 
{ 
    //Custom permission checking logic 
    return false;//no permission for all methods-Just for testing 
} 

public override void OnAuthorization(AuthorizationContext filterContext) 
{ 
    base.OnAuthorization(filterContext); 
    CheckIfUserIsAuthenticated(filterContext);} 
} 

private void CheckIfUserIsAuthenticated(AuthorizationContext filterContext) 
{ 
    // If Result is null, we’re OK: the user is authenticated and authorized. 
    if (filterContext.Result == null) 
     return; 

    var httpContext = filterContext.HttpContext; 
    var request = httpContext.Request; 
    var response = httpContext.Response; 

    var user = httpContext.User; 
    // If here, you’re getting an HTTP 401 status code. In particular, 
    // filterContext.Result is of HttpUnauthorizedResult type. Check Ajax here. 

    if (request.IsAjaxRequest()) 
    { 
     if (user.Identity.IsAuthenticated == false) 
      response.StatusCode = (int)HttpStatusCode.Unauthorized;//401 
     else 
      response.StatusCode = (int)HttpStatusCode.Forbidden;//403 

     response.SuppressFormsAuthenticationRedirect = true; 

     response.End();// This line is causing the problems 

     return; 
    } 

    if (user.Identity.IsAuthenticated) 
    { 
     //Redirect to customerror page 
    } 
} 

Вопрос в том, когда я звоню метод с использованием AJAX поста, мой пользовательское исключением фильтр ловит ошибку говоря "Server cannot set status after HTTP headers have been sent " Если удалить response.end(), я получаю 401 ответа в Аякса метод обработчика ошибок вместо 403. Я попытался

HttpContext.Current.ApplicationInstance.CompleteRequest() 

вместо response.end, но тогда и я получаю 401 ошибку

Т здесь, во всяком случае, чтобы избежать этого исключения?

Update Я использую этот общий метод обработчика ошибок в JavaScript, чтобы поймать все ошибки Ajax запроса (нужно правильный код статуса для ответа):

function ajaxFailed(xhr, textstatus, errorthrown) { 
    debugger; 
    if (textstatus == "error") { 
     if (xhr.status == 401) { 
      window.location = "/Account/Login"; 
     } 
     if (xhr.status == 403) { 
      $("#divoutput").html("you don't have permission."); 
     } 
    } 
    if (xhr.status == 500) { 
     $("#divoutput").append("<br/> internal servererror." + xhr.responseText); 
    } 
} 

Update 2: Мой текущий Решение: Проверьте свойство Exception.Message повышенного исключения в моем настраиваемом обработчике обработчика исключений и проигнорируйте его, если это сообщение: «Сервер не может установить статус после HTTP-заголовка s были отправлены ".

Я знаю, что это неэффективный метод, но у меня пока нет другого решения. Ожидание хорошее решение :)

ответ

0

Try изменить порядок обработки запроса:

public override void OnAuthorization(AuthorizationContext filterContext) 
{ 
    CheckIfUserIsAuthenticated(filterContext);} 
    base.OnAuthorization(filterContext); 
} 

Update:

В статье вы связаны говорит, что вы должны обращаться с другой метод обработчик событияHandleUnauthorizedRequest:

protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) 

Н от OnAuthorization, как и вы.

Update # 2:
Попытка использовать буферизацию вывода с

Response.BufferOutput = true; 

так предупреждается ваш сервер отправить заголовки обратно клиенту.

+0

if (filterContext.Result == null) всегда верно, если я это сделаю. – Sharun

+0

Это потому, что проверки не проводились, но заголовки не были отправлены. – VMAtm

+0

Я тебя не понимаю. Мне нужно сначала выполнить base.OnAuthorization (filterContext), чтобы свойство user.Identity.IsAuthenticated было правильно настроено. Затем в моем обычном методе я проверяю это значение, чтобы найти, является ли это проблемой аутентификации или проблемой авторизации. – Sharun