Asp.net Mvc пользовательский механизм для обработки несанкционированных запросов - PullRequest
20 голосов
/ 09 августа 2011

Для моего сайта я хочу следующие действия для защищенного контроллера (или действия)

, если пользователь делает обычный запрос перенаправления на страницу входа (что я легко могу сделать)

, еслизапрос типа Ajax Request.IsAjaxRequest()==true, код возврата 401

Как мне создать фильтр для этого ??

Ответы [ 6 ]

27 голосов
/ 10 августа 2011
 public class MyCustomAuthorize : AuthorizeAttribute
{
        protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
        {
            //if ajax request set status code and end Response
            if (filterContext.HttpContext.Request.IsAjaxRequest())
            {
                filterContext.HttpContext.Response.StatusCode = 401;
                filterContext.HttpContext.Response.End();
            }

            base.HandleUnauthorizedRequest(filterContext);
        }
}

Создайте фильтр, как указано выше, он вернет код состояния 401 для неавторизованного запроса, если запрос сделан через ajax.

Если вы используете jQuery, вы можете сделать, как показано ниже

jQuery.ajax({
statusCode: {
    401: function() {
      alert('unauthrized');
    },

  /*other options*/
});
4 голосов
/ 25 января 2014

В дополнение к принятому ответу мне нужно было вставить эту строку кода, чтобы предотвратить перенаправление FormsAuthentication на страницу входа в систему.

filterContext.HttpContext.Response.SuppressFormsAuthenticationRedirect = true;

я потом убрал filterContext.HttpContext.Response.End ();

var unauthorizedResult = new JsonResult
{
    Data = new ErrorResult() {Success = 0, Error = "Forbidden"},
            JsonRequestBehavior = JsonRequestBehavior.AllowGet
    };
    // status code
    filterContext.HttpContext.Response.StatusCode = (int) HttpStatusCode.Unauthorized;
    // return data
    filterContext.Result = unauthorizedResult;
    filterContext.HttpContext.Response.SuppressFormsAuthenticationRedirect = true;
}
1 голос
/ 09 августа 2011

Вы можете просто вернуть HttpUnauthorizedResult .

Примечание: Это может привести к тому, что инфраструктура MVC вернет вас на страницу входа.

public ActionResult FailResult()
{
        return new HttpUnauthorizedResult();
}
1 голос
/ 09 августа 2011

Вы можете использовать ajaxonly , чтобы ограничить доступ к ajax actionresult

1 голос
/ 09 августа 2011

Ваша проблема не в запросе AJAX, ваша проблема в возврате HTTP 401 Несанкционированного ответа, потому что вы используете проверку подлинности с помощью форм. Этот код ответа сообщает платформе, что он должен перенаправить пользовательский агент на вашу страницу входа с ответом HTTP 302. Вот почему было легко настроить «нормальное» перенаправление запросов - это делается автоматически.
Чтобы ответить на ваш вопрос, у меня была похожая проблема, и в результате я решил не использовать проверку подлинности с помощью форм. Я реализовал пользовательский атрибут авторизации, который обрабатывает оба случая вручную. Я не уверен, что это лучший подход, но он работает. Мне интересно, что другие думают об этом решении или какие есть другие решения.
К счастью, вы все еще можете использовать класс FormsAuthentication для обработки файлов cookie для вас, но вам нужно удалить конфигурацию аутентификации форм из вашего файла Web.config. Когда пользователь входит в систему, вы используете FormsAuthentication.SetAuthCookie, чтобы установить cookie (вы, вероятно, уже делаете это). Во-вторых, в своем атрибуте авторизации вы получаете куки-файл из запроса и используете FormsAuthentication.Decrypt для его расшифровки. Если он существует и действителен, вы устанавливаете пользователя в HttpContext на основе этого файла cookie, потому что проверка подлинности с помощью форм больше не сделает это за вас. Если это не так, вы либо перенаправляете на страницу входа, либо возвращаете 401, в зависимости от того, является ли это вызовом AJAX или нет.

0 голосов
/ 28 ноября 2016

простой способ сделать проверку в действии SignIn

public ActionResult SignIn()
{
    if (Request.IsAjaxRequest())
    {
        // you could return a partial view that has this script instead
        return Content("<script>window.location = '" + Url.Action("SignIn", "Account") + "'</script>");
    }
   ...
   return View();
...