对 ASP.Net MVC 的授权进行更多控制; 保留 AJAX 请求 AJAXy

发布于 2024-07-22 18:44:07 字数 524 浏览 6 评论 0原文

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

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

我遇到的问题是我通过 AJAX 发送请求到 Comment/Create,

X-Requested-With=XMLHttpRequest

这有助于将请求识别为 AJAX。 当用户未登录并点击授权墙时,它会被重定向到

/Account/LogOn?ReturnUrl=Comment%2fCreate

这会破坏 AJAX 工作流程。 我需要重定向到

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

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

I have some action methods behind an Authorize like:

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

The problem I have is that I'm sending a request through AJAX to Comment/Create with

X-Requested-With=XMLHttpRequest

which helps identify the request as AJAX. When the user is not logged in and hits the Authorize wall it gets redirected to

/Account/LogOn?ReturnUrl=Comment%2fCreate

which breaks the AJAX workflow. I need to be redirected to

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

Any ideas how that can be achieved? Any ways to gain more control over what happens when Authorization is requested?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

要走干脆点 2024-07-29 18:44:07

感谢刘易斯的评论,我能够达到这个解决方案(这远非完美,用我自己的评论发布,如果您有修复,请随意编辑并删除这个短语),但它有效:

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

Thanks to Lewis comments I was able to reach this solution (which is far from perfect, posted with my own comments, if you have the fixes feel free to edit and remove this phrase), but it works:

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);
        }
    }
}
黑色毁心梦 2024-07-29 18:44:07

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

Recently I ran into exactly the same problem and used the code posted by J. Pablo Fernández
with a modification to account for return URLs. Here it is:

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);
        }
    }
}
囚你心 2024-07-29 18:44:07

我没有使用授权属性,而是做了类似以下的事情。

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

Instead of using the authorize attribute, I've been doing something like the following.

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 = ?? });
    }
}
戏剧牡丹亭 2024-07-29 18:44:07

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

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

但是,如果这不能满足您的需求。
您可以尝试编写自己的授权操作过滤器,也许继承 MVC 框架附带的过滤器,但按照您想要的方式重定向。 这相当简单。

I think the right way to handle this would be in your Javascript making the AJAX call.

If the user needs to be authorized (or authenticated as your code implies) and isn't, you should inform them and maybe not allow them to try and comment in the first place.

However, if that doesn't suit your needs.
You could try and write your own authorize action filter, maybe inheriting from the one that comes with the MVC framework but redirects how you want it to. It's fairly straightforward.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文