代码之家  ›  专栏  ›  技术社区  ›  Alex from Jitbit

表单身份验证和来自AJAX的POST请求

  •  6
  • Alex from Jitbit  · 技术社区  · 15 年前

    我们有一个受表单身份验证保护的ASP.NET应用程序。该应用大量使用MS-AJAX调用其web服务。

    当窗体身份验证超时时 得到 -请求发生-一切正常(用户被重定向到登录页面)。

    当窗体身份验证超时且 -请求发生(ajax)-没有重定向发生,相反,应用程序返回“401Unahorized”,浏览器提示输入用户名和密码(不是登录表单,而是浏览器内置的对话框)。当然,输入任何用户名/密码都不会有帮助。

    我该怎么处理?

    在查看firebug之后,我刚刚发现常规POST请求重定向到登录fine,只有web服务调用抛出“401未授权”。 常规请求和web服务之间的区别在于URL。它是“page.aspx”,用于常规post请求,是“service.asmx/MethodName”,用于Web服务。。。

    2 回复  |  直到 15 年前
        1
  •  2
  •   Alex from Jitbit    15 年前

    好的,回答我自己的问题。

    在研究了这个问题并进行了更多的研究之后,我发现当一个web应用程序受到表单身份验证的保护时,用户 ,情况就是这样:

    • 如果是GET请求,则用户是
    • 如果是对页面的POST请求,则用户是
    • 如果这是一个POST请求 - 用户未经授权获取401

    如果一个web服务被AJAX(xmlHttpRequest对象)调用并返回401,那么浏览器当然会显示一个弹出的登录框。

    现在,您应该做的是向应用程序\u PostAuthenticateRequest添加一些代码,以防止抛出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);
    }
    
        2
  •  1
  •   PanJanek    15 年前

    我看到两种解决办法:

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

    这样,只要浏览器窗口打开,会话就不会过期。

    (2) 在每个ajax请求上检查响应的状态。如果响应包含“401 unauthorized”代码(或与200不同的任何其他代码),则表示会话已过期,而不是将响应加载到页面中的某个对话框中,而是将用户重定向到登录页面。

    最好的解决办法是将上述两种机制结合起来。只要页面在浏览器中显示,心跳机制将有助于保持会话活动。但这并不能保证这一点。会话过期时,可以断开与服务器的连接并重新打开。因此,无论如何,您都应该检查响应状态。