我正在制作一个ASP.Net MVC3应用程序。我现在使用Visual Studio 2010项目附带的内置身份验证代码。问题是我需要在登录后立即检索登录用户的数据库ID。我现在通过将代码添加到帐户控制器的登录操作来执行此操作,该控制器通过用户名查找数据库中的ID 。这适用于新登录,但不适用于“记住”登录。在重新启动应用程序时,最后一个用户会再次自动登录,但不会触发登录代码,因此我没有获取数据库ID。
我该如何解决这个问题?
编辑: 我试图实现Daniel的解决方案看起来很有希望,我想出了这个代码。虽然它被召唤!我哪里出错?
的Global.asax.cs:
protected void Application_Start()
{
Database.SetInitializer<StandInContext>(new StandInInitializer());
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
this.AuthenticateRequest +=
new EventHandler(MvcApplication_AuthenticateRequest);
}
void MvcApplication_AuthenticateRequest(object sender, EventArgs e)
{
if(Request.IsAuthenticated)
{
using (var db = new StandInContext())
{
var authenticatedUser = db.AuthenticatedUsers.SingleOrDefault(
user => user.Username == User.Identity.Name);
if (authenticatedUser == null)
return;
var person = db.Persons.Find(authenticatedUser.PersonID);
if (person == null)
return;
Context.User = new CustomPrincipal(
User.Identity, new string[] { "user" })
{
Fullname = person.FullName,
PersonID = person.PersonID,
};
}
}
}
答案 0 :(得分:3)
您可以在Global.asax.cs中使用AuthenticateRequest
事件:
protected void Application_AuthenticateRequest()
{
if (Request.IsAuthenticated)
{
// retrieve user from repository
var user = _membershipService.GetUserByName(User.Identity.Name);
// do other stuff
}
}
<强>更新强>
既然我已经看到你想要做的更清楚一些,我建议不要在这种特殊情况下使用会话。一个原因是Session需要引用System.Web
,您无法从某些地方访问,例如单独的类库中的业务逻辑层。另一方面,IPrincipal
因此而存在。
如果您需要存储比IPrincioal提供的更多用户信息,您只需实现它并向其添加您自己的属性。更容易,您可以从GenericPrincipal
派生,它实现了IPrincipal并添加了一些基本的角色检查功能:
<强> CustomPrincipal.cs 强>
public class CustomPrincipal : GenericPrincipal
{
public CustomPrincipal(IIdentity identity, string[] roles)
: base(identity, roles) { }
public Guid Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
...
}
然后你像以前一样用AuthenticateRequest
替换你自己的默认主体:
<强>的Global.asax.cs 强>
protected void Application_AuthenticateRequest()
{
if (Request.IsAuthenticated)
Context.User = _securityService.GetCustomPrincipal(User.Identity.Name);
}
就是这样。您获得的最大好处是可以自动从任何地方访问您的用户数据,而无需将 userId 参数粘贴到您的所有方法中。您需要做的就是将当前主体转换回CustomPrincipal,并像这样访问您的数据:
从您的剃须刀视图:
<p>Hello, @((CustomPrincipal)User).FirstName!</p>
来自您的控制器:
var firstName = ((CustomPrincipal)User).FirstName;
来自另一个程序集中的业务逻辑层:
var firstName = ((CustomPrincipal)Thread.CurrentPrincipal).FirstName;
为了保持DRY,您可以将其打包为扩展方法并将其挂起IPrincipal,如下所示:
public static class PrincipalExtensions
{
public static string GetFirstName(this IPrincipal principal)
{
var customPrincipal = principal as CustomPrincipal;
return customPrincipal != null ? customPrincipal.FirstName : "";
}
}
然后你会@User.GetFirstName()
,var userName = User.GetFirstName()
,Thread.CurrentPrincipal.GetFirstName()
等。
希望这有帮助。
答案 1 :(得分:1)
我没有想清楚。我试图将userinfo存储在Session对象中,而它可以通过User对象获得。抱歉浪费了你的时间。