简体   繁体   中英

How to use custom AuthorizeAttribute with AJAX

With help of fellow friends I managed to find a solution for my problem from this topic: Reusable way to allow an account to be used by a single person at a time

I have a SingleLogin class which inherits from AuthorizeAttribute and implements a custom AuthorizeCore method for the purpose of re-usability of my single-login code:

    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        bool isAuthorized = base.AuthorizeCore(httpContext);

        if (isAuthorized)
        {
            int userId = (int)WebSecurity.CurrentUserId;
            using (var db = new UsersContext())
            {
                if ((httpContext.Session.SessionID != db.getSessionId(userId))
                    || db.getSessionId(userId) == null)
                {
                    WebSecurity.Logout();
                    isAuthorized = false;
                    httpContext.Response.Redirect("/Home/Index");
                }
            }
        }

        return isAuthorized;
    }

Everything works fine except my JsonResult action:

    [HttpPost]
    public JsonResult MessageSave(string message)
    {
        bool messageSaved = false;
        int userId = (int)WebSecurity.CurrentUserId;
        message = HttpUtility.HtmlEncode(message);

        // Model method - adding chat log - db
        db.addChatLog(message, userId);
        messageSaved = true;

        return Json(new { messageSaved = messageSaved });
    }

This method is triggered by Ajax POST call which you can see in code example below. Just basic POST.

EDIT 3 Please check these images: http://imgur.com/a/Cjael .. Hm I guess POST does trigger, but have no idea why does my alert not work when I try to test it before $.ajax ... As you can see in response I do get Home/Index page but I am not redirected to home/index immediately(text stays inside of textBox and page just waits..), I have to push enter one more time to be redirected.. Very strange.

EDIT2 Seems like I can't even access my jQuery even after I get logged out. I put some alerts inside of my .js file.

I have a separate .js file which is then put in my View as <script src="~/Scripts/custom/homeChat.js"></script> . I pass the Razor values from View into my JS file via HTML5 data-.

My textBox element #txtMsg, triggers my jQuery event, therefore when I am logged out it probably doesn't recognize my textBox element anymore, and doesn't trigger my jQuery event?

Element that triggers .js in view is: @Html.TextBox("txtMsg")

JS:

$("#txtMsg").keypress(function (e) {

        //when enter
        if (e.which == 13) {
            alert("ALERT DOESNT TRIGGER");

                $.ajax({
                    type: "POST",
                    url: url,
                    data: JSON.stringify({ message: input }),
                    contentType: "application/json; charset=utf-8",
                    dataType: "json",
                    success: function (data) {
                        if (data.messageSaved) {
                            $("#txtMsg").val("");
                        }
                        else {
                            window.location.href = urlhome;
                        }
                    }
                });
            }
        }
    });

So if you can't even come into your event, how can you even know something went wrong? I have this ˙HandleUnauthorizedRequest but you are required that you can get into your jQuery event(in my case .keypress in the js code above) for this to work if I understand right.

EDIT: Additional explanation

So let me explain the scenario. If I login with my username "john" from Firefox and again with username "john" from chrome, next action I do in Firefox, it will log me out and redirect me to Home/Index, because someone else made a new login in Chrome.

That is ok. Since you are not logged in anymore, you get redirected normally to your Home/Index if your action is normal ActionResult and returns view.

The problem I have is, that I have some other functionality in the page, which uses Ajax POST, and since you are logged out you can't POST to that JsonResult action therefore you can't even receive callback of error, which redirects you to Home/Index. I put some alerts into my JS, but no alert triggers which is normal, because I am not allowed on that page anymore anyway. If I want that my onEnter textbox redirects me to Home/Index I have to press enter twice. Is that all that could be done?

I am interested in best approach for this AJAX problem. I don't know how I should call it, but as I read from my previous topic it is called "handling AJAX timeouts"?

Thank you very much.

If understand it correctly you want to handle the unauthorized ajax request .

In that case you can override the HandleUnauthorizedRequest method in your attribute:

protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
    if (filterContext.HttpContext.Request.IsAjaxRequest()) 
    {
        filterContext.HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
        filterContext.Result = new JsonResult();
    }
    else
    {
        filterContext.Result = new HttpStatusCodeResult((int)HttpStatusCode.Forbidden);
    }
}

You can handle errors on AJAX request this way

$.ajax({
    type: "POST",
    url: url,
    data: JSON.stringify({ message: input }),
    contentType: "application/json; charset=utf-8",
    dataType: "json",
    success: function (data) {
        if (data.messageSaved) {
            $("#txtMsg").val("");
        }
        else {
            window.location.href = urlhome;
        }
    },
    error: function(xhr, status, error) {
        // TODO: may be check error or status or xhr.statusCode()
        window.location.href = urlhome;
    }
});

jQuery $.ajax() docs

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM