【问题标题】:More control on ASP.Net MVC's Authorize; to keep AJAX requests AJAXy对 ASP.Net MVC Authorize 的更多控制;保持 AJAX 请求 AJAX
【发布时间】:2010-10-30 21:49:51
【问题描述】:

我在 Authorize 后面有一些操作方法,例如:

[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

有什么想法可以实现吗?有什么方法可以更好地控制请求授权时发生的事情?

【问题讨论】:

    标签: asp.net-mvc ajax authorize


    【解决方案1】:

    我没有使用 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 = ?? });
        }
    }
    

    【讨论】:

    • 我已经搞定了那部分。我的问题是该方法前面有一个 Authorize 并且 Authorize 的重定向失去了像您一样检查 AJAX 的能力。
    【解决方案2】:

    我认为处理此问题的正确方法是在您的 Javascript 中进行 AJAX 调用。

    如果用户需要被授权(或如您的代码所暗示的那样进行身份验证)并且不需要,您应该通知他们并且可能不允许他们首先尝试和评论。

    但是,如果这不符合您的需求。 您可以尝试编写自己的授权操作过滤器,可能继承自 MVC 框架附带的过滤器,但会重定向您想要的方式。这很简单。

    【讨论】:

    • 我希望他们尝试评论和参与该站点,并且仅在必要时提示登录。在 JavaScript 代码中,我无法知道用户是否已登录,而无需先进行 AJAX 调用来检查,然后再尝试执行该功能。我喜欢你做另一个动作过滤器的想法,但是在玩了一点之后,它似乎无法控制用户被重定向到的位置。你肯定知道吗?还有其他提示吗?
    • 我的错,现在我找到了。感谢刘易斯正确方向的指针。
    【解决方案3】:

    感谢 Lewis cmets,我能够找到这个解决方案(这远非完美,用我自己的 cmets 发布,如果您有修复,请随时编辑和删除此短语),但它确实有效:

    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);
            }
        }
    }
    

    【讨论】:

    • 很好的例子。但是如何测试 base.OnAuthorization(filterContext);调用?
    • Kevin Craft描述了解决这个问题的另一种方法
    【解决方案4】:

    最近我遇到了完全相同的问题,并使用了 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);
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-23
      • 2015-02-14
      • 2016-11-26
      • 1970-01-01
      相关资源
      最近更新 更多