ASP.NET 3.5 MVC1 - 用户随机未经身份验证/需要重新登录

时间:2011-01-31 21:11:05

标签: c# asp.net-mvc session forms-authentication

我们使用IIS 7进行进程外SQL会话状态,ASP.NET 3.5 MVC 1.0和表单身份验证。

用户的会话在登录时正确设置,并将按预期超时,将其重定向到特殊的“超时”登录页面。问题是一些(并非所有)用户登录并且(我可以告诉他们)立即未经身份验证并且需要重新登录(即重定向到原始的“登录”页面)。

可能有人知道为什么我们的用户会被间歇性地踢出去?

编辑:我已经在每个Application_AuthenticateRequest事件中添加了日志记录,我可以告诉您,在用户启动之前,Auth票证都经过身份验证,持久性并在两天后过期,并且请求也经过身份验证。到达登录页面后,用户不再进行身份验证。

编辑#2:我们取得了一些进展,似乎用户可能未经身份验证,因为此Web应用程序正在查找未对用户进行身份验证的父应用程序中的脚本和其他内容。包含这些脚本的原始格式如下:

<script src="../../Scripts/MicrosoftAjax.js" type="text/javascript"></script>

我已将其更正为:

<script src="<%= Url.Content("~/Scripts/MicrosoftAjax.js") %>" type="text/javascript"></script>

答案我们.master页面中对脚本引用的上述更改解决了该问题。它明确告诉应用程序查看当前应用程序的根文件夹。感谢所有帮助过的人。我希望我可以标记不止一个作为答案!

以下是我们的登录操作:

    [AcceptVerbs(HttpVerbs.Post)]
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings",
        Justification = "Needs to take same parameter type as Controller.Redirect()")]
    public virtual ActionResult LogOn(string userName, string password, string returnUrl)
    {
        if ((HttpContext.Current.User == null) || (!HttpContext.User.Identity.IsAuthenticated))
        {
          if (!ValidateLogOn(userName, password))
          {
              try
              {
                return View();
              }
              catch (Exception ex)
              {
                throw new Exception(string.Format("User validation failed at LogOn: {0}", ex.ToString()));
              }
          }
        }

        bool rememberMe = true;

        FormsAuth.SignIn(userName, rememberMe);

        Session["userName"] = userName;

        if (!String.IsNullOrEmpty(returnUrl))
        {
            try
            {
                return Redirect(returnUrl);
            }
            catch (Exception ex)
            {
                throw new Exception(string.Format("User redirect to returnUrl ({0}) failed: {1}", returnUrl, ex.ToString()));
            }
        }
        else
        {
            try
            {
                return RedirectToAction("Index", "RodWebUI");
            }
            catch (Exception ex)
            {
                throw new Exception(string.Format("User redirect to action: Index, controller: RodWebUi failed: {0}", ex.ToString()));
            }
        }
    }

以下是我们的超时记录操作:

    public virtual ActionResult TimeOutLogon()
    {
        try
        {
            FormsAuth.SignOut();

            ViewData["TimeoutMsg"] = "Session timed out. Please log back in.";

            return View();
        }
        catch (Exception ex)
        {
            throw new Exception(string.Format("Error with redirecting to TimeOutLogon: {0}", ex.ToString()));
        }
    }  

我已经将以下检查添加到我们的global.asax中,以记录请求和身份验证票证的当前状态。在被踢回LogOn之前,所有内容都经过身份验证和确定。

    protected void Application_AuthenticateRequest(object sender, EventArgs e)
    {
        if (HttpContext.Current.User != null)
        {
            if (HttpContext.Current.User.Identity.IsAuthenticated)
            {
                if (HttpContext.Current.User.Identity is FormsIdentity)
                {
                    FormsIdentity identity = (FormsIdentity)HttpContext.Current.User.Identity;

                    FormsAuthenticationTicket ticket = identity.Ticket;

                    LogFunctionCall(HttpContext.Current.User.Identity.Name, "", "User Authentication Check", "", 
                                        string.Format("Auth ticket is expired: {0}, expiration date: {1}, is persistent: {2}, issued: {3}", 
                                        ticket.Expired, ticket.Expiration, ticket.IsPersistent, ticket.IssueDate), "", 0);

                    LogFunctionCall(HttpContext.Current.User.Identity.Name, "", "User Authentication Check Line #2", "", 
                                        string.Format("Raw URL: {0}, Request is authenticated: {1}", HttpContext.Current.Request.RawUrl, HttpContext.Current.Request.IsAuthenticated), "", 0);
                }
            }
        }
    }

5 个答案:

答案 0 :(得分:2)

如果用户未经过身份验证,或者他们无权查看他们尝试访问的资源,则会将用户重定向到登录页面。

答案 1 :(得分:2)

你有一个负载均衡的网站吗?

如果是这样,所有节点上的machineKeys是否相同? Forms Cookie名称是否相同?如果这些值存在差异,您可以在一个节点上登录,并且看起来未经身份验证到另一个节点。

答案 2 :(得分:1)

这可能很愚蠢,但 returnUrl 是否可以指向登录页面?

当用户已登录时,登录页面的行为如何?

答案 3 :(得分:1)

public partial class MasterPage : System.Web.UI.MasterPage
{
    protected void Page_Load(object sender, EventArgs e)
    {
    }
    protected void signout_Click(object sender, EventArgs e)
    {
      Response.Write("<script language=javascript>var wnd=window.open('','newWin','height=1,width=1,left=900,top=700,status=no,toolbar=no,menubar=no,scrollbars=no,maximize=false,resizable=1');</script>");
      Response.Write("<script language=javascript>wnd.close();</script>");
      Response.Write("<script language=javascript>window.open('login.aspx','_parent',replace=true);</script>");
      Session["name"] = null;
    }
}

我也在这个代码的所有页面上添加。

protected void Page_Load(object sender, EventArgs e)
    {
      Response.Cache.SetCacheability(HttpCacheability.NoCache);
      Response.Cache.SetAllowResponseInBrowserHistory(false);
    }
}

答案 4 :(得分:0)

Spidey sense表示ASP.NET进程或应用程序池正在回收您。可能由于一些原因而发生。由于会话不在进行中,因此不会被此活动吃掉。

我会查看事件日志,看看是否有任何紧急情况。