如何利用自动重复登录?

时间:2011-08-25 06:15:11

标签: asp.net-mvc asp.net-mvc-3 forms-authentication

我正在制作一个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,
                           };
        }
    }
}

2 个答案:

答案 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对象获得。抱歉浪费了你的时间。