我在.NET MVC4项目中使用SimpleMembership。在开发过程中,在手动操作/重建数据库的过程中,我遇到了一个在生产中不太可能发生的错误,但是我想解决这个问题,我找不到一种优雅的方法来处理它。
如果在登录应用程序后,您的用户名在数据库中被更改,或者您的用户记录被完全删除,则用户将无法再访问该应用程序的任何页面...包括允许匿名的公共页面视图和登录屏幕。相反,抛出异常 - “未找到具有名称'username'的用户”。
我的应用程序中的所有页面都显示部分视图,该视图呈现登录/注销控件。无论数据库中有什么,Request.IsAuthenticated都返回true。应用程序似乎认为用户仍然根据cookie中的信息登录,但是在数据库中找不到相应的记录。清除auth cookie解决了这个问题,但这不是我想要提供给可能遇到此问题的用户的指令。
我目前的解决方案是在Global.asax中捕获该异常,清除cookie并重定向到登录页面。这对我来说似乎完全是hacky。
有没有人有更好的解决方案?我从来没有遇到过使用旧的.NET成员资格提供商这样的问题...我的期望是这种情况应该开箱即用,我不应该考虑到它......如果记录被改变了/在数据库中删除,用户应该只是失败授权并自动重定向到登录页面。
答案 0 :(得分:1)
您可以在登录后检查数据库缓存或页面的某个位置,用户记录的依赖关系,它所依赖的位置,链删除或由于依赖注入而可能发生的情况。
请检查或请分享代码..
答案 1 :(得分:1)
不确定您的身份验证逻辑首先在哪里,但这就是我的工作:
在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(){}
答案 2 :(得分:1)
我遇到了同样的问题,IsAuthenticated
在我没有登录MVC 4网站时返回true
,导致出现相同的错误消息。
在我们的解决方案中,我有两个使用SimpleMembership的MVC 4站点,结果发现我在调试第二个站点时登录了第一个站点。
我认为这将与设置的cookie有关,因为两个站点都在localhost
en上的不同端口下运行,因此两者都将设置相同的身份验证cookie。我可能需要更改身份验证cookie的设置方式。
我认为你可能有不同的问题,但也许我的“解决方案”可以帮助有这个问题的人。
答案 3 :(得分: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();
}
}
答案 4 :(得分: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
答案 5 :(得分:-1)
这似乎是从您的开发环境切换到另一台主机时引起的。 localhost正在记住登录cookie并尝试将其用于新的简单成员资格数据库。
正如你所说,它不会在生产中发生。抱歉,我不知道在本地和生产数据库上使用相同登录的更好方法。