Больше контроля над ASP.Net MVC's Authorize; держать AJAX запросы AJAXy - PullRequest
5 голосов
/ 03 июня 2009

У меня есть несколько методов действия для Авторизации, например:

[AcceptVerbs(HttpVerbs.Post), Authorize]
public ActionResult Create(int siteId, Comment comment) {

Проблема в том, что я отправляю запрос через AJAX для комментирования / создания с

X-Requested-With=XMLHttpRequest

, который помогает идентифицировать запрос как AJAX. Когда пользователь не вошел в систему и не ударился об Авторизированную стену, он перенаправляется на

/Account/LogOn?ReturnUrl=Comment%2fCreate

, который нарушает рабочий процесс AJAX. Я должен быть перенаправлен на

/Account/LogOn?X-Requested-With=XMLHttpRequest

Есть идеи, как этого достичь? Любые способы получить больше контроля над тем, что происходит, когда запрашивается авторизация?

Ответы [ 4 ]

5 голосов
/ 04 июня 2009

Благодаря комментариям Льюиса я смог найти это решение (которое далеко не идеально, опубликовано с моими собственными комментариями, если у вас есть исправления, не стесняйтесь редактировать и удалять эту фразу), но оно работает:

public class AjaxAuthorizeAttribute : AuthorizeAttribute {
    override public void OnAuthorization(AuthorizationContext filterContext) {
        base.OnAuthorization(filterContext);
        // Only do something if we are about to give a HttpUnauthorizedResult and we are in AJAX mode.
        if (filterContext.Result is HttpUnauthorizedResult && filterContext.HttpContext.Request.IsAjaxRequest()) {
            // TODO: fix the URL building:
            // 1- Use some class to build URLs just in case LoginUrl actually has some query already.
            // 2- When leaving Result as a HttpUnauthorizedResult, ASP.Net actually does some nice automatic stuff, like adding a ReturnURL, when hardcodding the URL here, that is lost.
            String url = System.Web.Security.FormsAuthentication.LoginUrl + "?X-Requested-With=XMLHttpRequest";
            filterContext.Result = new RedirectResult(url);
        }
    }
}
3 голосов
/ 13 июля 2010

Недавно я столкнулся с точно такой же проблемой и использовал код, написанный J. Pablo Fernández с модификацией для учета обратных URL. Вот оно:

public class AuthorizeAttribute : System.Web.Mvc.AuthorizeAttribute
{
    override public void OnAuthorization(AuthorizationContext filterContext)
    {
        base.OnAuthorization(filterContext);
        // Only do something if we are about to give a HttpUnauthorizedResult and we are in AJAX mode. 
        if (filterContext.Result is HttpUnauthorizedResult && filterContext.HttpContext.Request.IsAjaxRequest())
        {
            // TODO: fix the URL building: 
            // 1- Use some class to build URLs just in case LoginUrl actually has some query already. 
            HttpRequestBase request = filterContext.HttpContext.Request;
            string returnUrl = request.Path;
            bool queryStringPresent = request.QueryString.Count > 0;
            if (queryStringPresent || request.Form.Count > 0)
                returnUrl += '?' + request.QueryString.ToString();
            if (queryStringPresent)
                returnUrl += '&';
            returnUrl += request.Form;
            String url = System.Web.Security.FormsAuthentication.LoginUrl +
                         "?X-Requested-With=XMLHttpRequest&ReturnUrl=" +
                         HttpUtility.UrlEncode(returnUrl);
            filterContext.Result = new RedirectResult(url);
        }
    }
}
1 голос
/ 03 июня 2009

Вместо использования атрибута authorize я делал что-то вроде следующего.

public ActionResult SomeCall(string someData)
{
    if (Request.IsAjaxRequest() == false)
    {
        // TODO: do the intended thing.
    }
    else
    {
        // This should only work with AJAX requests, so redirect
        // the user to an appropriate location.
        return RedirectToAction("Action", "Controller", new { id = ?? });
    }
}
0 голосов
/ 03 июня 2009

Я думаю, что правильный способ справиться с этим был бы в вашем Javascript, выполняющем вызов AJAX.

Если пользователь должен быть авторизован (или аутентифицирован, как предполагает ваш код), а это не так, вы должны сообщить ему об этом и, возможно, не разрешить ему пытаться комментировать.

Однако, если это не соответствует вашим потребностям. Вы можете попробовать написать свой собственный фильтр действий авторизации, возможно, наследующий от того, который поставляется с инфраструктурой MVC, но перенаправляет, как вы хотите. Это довольно просто.

...