.NET MVC4中的SimpleMembership错误 - "未找到用户名为xxx的用户"

6
我正在使用SimpleMembership在我的.NET MVC4项目中。在开发过程中,当手动操作/重建数据库时,我遇到了一个错误,在生产环境中不太可能出现,但我想解决这个问题,我找不到一个优雅的方法来处理它。
如果在登录应用程序后,您的用户名在数据库中更改或者您的用户记录完全删除,则用户将无法访问应用程序的任何页面...包括允许匿名视图的公共页面和登录屏幕。相反,会抛出异常-"未找到名称为'用户名'的用户"。
我的应用程序中所有页面都显示呈现登录/注销控件的部分视图。无论数据库中有什么内容,Request.IsAuthenticated都返回true。似乎应用程序认为用户仍然已登录,基于cookie中的信息,但在数据库中找不到相应的记录。清除auth cookie可以解决此问题,但这不是我想要向可能遇到此问题的用户提供的指令。
我的当前解决方案是在Global.asax中捕获该异常,清除cookie并重定向到登录页面。对我来说,这似乎完全是一个 hacky 解决方案。
是否有人对这种情况有更好的解决方案?我从未遇到过使用旧的.NET Membership提供程序出现这样的问题...我的期望是,这种情况应该被默认覆盖,我不应该对此进行说明...如果记录在DB中被更改/删除,则用户应该失败授权并自动重定向到登录页面。
6个回答

2

不确定你是否首先将认证逻辑放在哪里,但这是我所做的:

在Global.asax.cs中:

    protected void Application_Error(object sender, EventArgs e)
    {
        Exception ex = Server.GetLastError();

        if (ex.Message.Contains("No user found was found that has the name"))
        {
            FormsAuthentication.SignOut();
            Response.Redirect(Request.RawUrl);
        }
    }

由于抛出的异常只是一个System.InvalidOperationException,所以你无法对其进行太多操作。虽然不太聪明,但却能完成必须的任务。同时,请确保在您重定向到的页面上没有类似IsUserInRole(...)的身份验证逻辑,如果有,则可能需要将其包装在try{} catch(){}中。


1
我遇到了同样的问题,IsAuthenticated返回true,但我没有登录MVC 4网站,结果出现了相同的错误信息。在我们的解决方案中,我有两个使用SimpleMembership的MVC 4网站,结果在调试第二个网站时,我已经登录了第一个网站。我认为这可能与cookie有关,因为两个网站在localhost上以不同的端口运行,所以两个网站将设置相同的身份验证cookie。我可能需要更改如何设置身份验证cookie。我认为你可能有不同的问题,但也许我的“解决方案”能帮助遇到此问题的人。

1
这个解决方案对我很有效,我先前登录了另一个网站,当我切换回来时出现了这个错误。只需清除缓存/ cookie,它就可以正常工作。 - Asad Ullah

1

您能否检查一下数据库缓存,或者页面某个地方,在登录后用户记录的依赖关系上,它可能是链式删除,也可能是由于依赖注入而发生。

请检查一下,或者分享一下代码。


0

覆盖AuthorizeAttribute:

public sealed class AuthorizeAttribute : System.Web.Http.AuthorizeAttribute
{
  protected override bool IsAuthorized(HttpActionContext actionContext)
  {
    try
    {
      return base.IsAuthorized(actionContext);
    }
    catch
    {
      return false; // user name from cookie is no longer in db
    }
  }

  protected override void HandleUnauthorizedRequest(HttpActionContext actionContext)
  {
    // handle this exception by global exception filter for redirection to login
    throw new CustomAuthException(); 
  }
}

0

我已经在Arman Bimatov的回复中添加了内容,以便在重定向到当前页面之前将您注销。通过重定向到当前页面,returnURL将被正确放置到查询字符串中。

在Global.asax.cs文件中:

protected void Application_Error(object sender, EventArgs e)
    {
      Exception ex = Server.GetLastError();
if (ex.Message.Contains("No user found was found that has the name")) { FormsAuthentication.SignOut(); Response.Redirect(Request.RawUrl); } }

但是,除非您在web.config中有一个CustomerErrors部分,否则此方法将无法正常工作,具体请参考以下问题: global.asax Application_Error not firing


https://dev59.com/t3A65IYBdhLWcg3wogKe - Daniel - SDS Group

-1

这似乎是在从开发环境切换到另一个主机时引起的问题。本地主机会记住登录 cookie 并尝试将其用于新的简单成员资格数据库。

正如您所说,这在生产中不会发生。抱歉,除了在本地和生产两个数据库上使用相同的登录之外,我不知道更好的方法。


我想在生产环境中仍然会发生这种情况,我的意思是在生产环境中,我不会手动删除数据库中的记录,因此很可能不会发生。这不是切换主机的问题。我没有花太多时间来尝试解决这个问题,但基本上与浏览器中的身份验证 cookie 有关,该 cookie 引用了数据库中不再存在的用户... 我希望这个问题能够更优雅地处理。 - Gadget27

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接