Forms Authentication and POST requests from AJAX

前端 未结 2 1184
萌比男神i
萌比男神i 2021-01-18 12:42

We have an ASP.NET app protected by forms authentication. The app uses MS AJAX heavily to call its web-services.

When the forms authentication times out, and a

相关标签:
2条回答
  • 2021-01-18 13:24

    I see two solutions:

    (1) "Heart beat" mechanism. On each page include a script that will "ping" the server by some dummy ajax request, like:

    <script>
       setInterval(ping, 60000); // based on comment by John
       function ping()
       {
           $.get('/do/nothing');
       }
    </script>
    

    This way the session shouldn't expire as long as the browser window is open.

    (2) On each ajax request check the status of the response. If the response has "401 unauthorized" code (or any other code different that 200), that means that the session expired and instead of loading the response into some dialog box in the page redirect the user to login page.

    Conclusion based on comments:

    The best solution would be to combine the two above mechanisms. Heartbeat mechanism will help to keep the session alive as long as the page is displayed in the browser. But in doesn't guarantee that for sure. The connection to the server can be broke and reopened when the session is expired. So you should check the response status anyway.

    0 讨论(0)
  • 2021-01-18 13:34

    Ok, answering my own questin.

    After looking into this issue and researching a bit more I found that when a web-app is protected by Forms-Authentication and the user is not authenticated, this is what happens:

    • If it's a GET-request - the user is redirected to the login page.
    • If it's a POST-request to a page - the user is redirected to the login page.
    • If it's a POST-request to a web-service - the user gets 401-unauthorized

    Thats how ASP.NET works

    And if a web-service is called by AJAX (xmlHttpRequest object) and returns 401 - of course the browser shows a pop-up login box.

    Now, what should you do is add some code to Application_PostAuthenticateRequest that will prevent throwing 401 for webservices.

    protected void Application_PostAuthenticateRequest(Object sender, EventArgs e)
    {
        if (Request.RequestType == "POST" //if its POST
            && !User.Identity.IsAuthenticated //if user NOT authed
            && !HasAnonymousAccess(Context) //if it's not the login page
            )
        {
            //lets get the auth type
            Configuration config = WebConfigurationManager.OpenWebConfiguration("~");
            SystemWebSectionGroup grp = (SystemWebSectionGroup)config.GetSectionGroup("system.web");
            AuthenticationSection auth = grp.Authentication;
            //if it FORMS auth
            if(auth.Mode== AuthenticationMode.Forms)
            {
    
                //then redirect... this redirect won't work for AJAX cause xmlHttpRequest can't handle redirects, but anyway...
                Response.Redirect(FormsAuthentication.LoginUrl, true);
                Response.End();
    
            }
        }
    }
    public static bool HasAnonymousAccess(HttpContext context)
    {
        return UrlAuthorizationModule.CheckUrlAccessForPrincipal(
            context.Request.Path,
            new GenericPrincipal(new GenericIdentity(string.Empty), null),
            context.Request.HttpMethod);
    }
    
    0 讨论(0)
提交回复
热议问题