如何使用AspNetSqlMembershipProvider进行多个并发会话?

时间:2011-12-05 20:40:33

标签: asp.net-mvc-3 asp.net-membership

我目前正在实施一个网站,要求“客户支持”用户以客户身份登录以获得支持。问题是,使用客户用户登录会中断客户支持登录,因此只能从一台计算机同时登录一个用户。

我将MVC3与AspNetSqlMembershipProvider一起用于授权\验证目的。

如何在一台计算机上轻松使用多个并发登录?

3 个答案:

答案 0 :(得分:2)

您应该在比经过身份验证的用户更高的层次上抽象它。我建议您介绍登录用户和当前用户的概念。会话保留在登录用户中,但具有足够权限的登录用户可以模拟其他用户,该用户将成为当前用户。使用当前用户来控制对数据的访问,驱动UI(模拟用户需要控制模拟的例外情况),执行事务等。将当前用户存储在会话中作为数据,可能在一个上设置常用属性根据需要OnActionExecuting中的基本控制器。

public class AdminController : BaseController
{

    [Authorize( Roles = "ActOnBehalfOfUser" )]
    [AcceptVerbs( HttpVerbs.Get )]
    public ActionResult Impersonate()
    {
        return View();
    }

    [Authorize( Roles = "ActOnBehalfOfUser" )]
    [AcceptVerbs( HttpVerbs.Post )]
    [ValidateAntiForgeryToken]
    public ActionResult Impersonate( string userNameOrID, bool? revoke )
    {
        var currentUser = this.GetCurrentUser();

        if (revoke.HasValue && revoke.Value)
        {
            try
            {
                LogImpersonationEnd( currentUser );
            }
            catch { }
            this.SetEffectiveUser( currentUser );
        }
        else
        {
            if (string.IsNullOrEmpty( userNameOrID ))
            {
                this.ModelState.AddModelError( "userNameOrID", "You must supply a username or uid to impersonate." );
                return View();
            }

            var person = this.LookupUser( userNameOrID );
            if (person == null)
            {
                this.ModelState.AddModelError( "userNameOrID", "No user with the given id was found." );
                return View();
            }

            this.SetEffectiveUser( person );
            try
            {
                using (var dc = new FooDataContext())
                {
                    var impersonation = new Impersonation
                    {
                        EffectiveUser = person.UID,
                        ActualUser = currentUser.UID
                    };
                    dc.InsertOnSubmit( impersonation );
                    dc.SubmitChanges();
                }
            }
            catch { }
        }

        return View();

    }
}

基础控制器:

public class BaseController : Controller
{
    protected bool IsImpersonating
    {
        get
        {
            var effectiveUID = this.Session[EFFECTIVE_USER_KEY] as string;
            var uid = this.Session[USER_KEY] as string;
            return !string.Equals( effectiveUID, uid );
        }
    }

    protected Person GetEffectiveUser()
    {
        return GetUser( this.Session[EFFECTIVE_USER_KEY] as string );
    }

    protected void SetEffectiveUser( Person person )
    {
        this.Session[EFFECTIVE_USER_KEY] = person.UniversityID;
        this.Session[UIPERSON_KEY + person.UniversityID] = person;
    }

    protected Person GetUser( string uid )
    {
        Person person = null;
        if (!string.IsNullOrEmpty( uid ))
        {
            person= GetCachedPerson( uid, p => p.UID == uid );
        }
        return person ?? new AnonymousPerson();
    }



    protected Person LookupUser( string usernameOrUID )
    {
        Person person = null;
        if (!string.IsNullOrEmpty( usernameOrUID ))
        {
            uiPerson = this.GetCachedPerson( usernameOrUID, p => p.UID== usernameOrUID || p.Username == usernameOrUID );
        }
        return uiPerson;
    }

    private Person GetCachedPerson( string uid, Expression<Func<Person, bool>> selector )
    {
        Person person = this.Session[PERSON_KEY + uid] as Person;
        if (person == null)
        {
            using (var context = new FooDataContext())
            {
                person = context.SingleOrDefault<Person>( selector );
                if (uiPerson != null)
                {
                    this.Session[PERSON_KEY + uid] = person;
                }
            }
        }
        return person;
    }

    protected void LogImpersonationEnd( Person currentUser )
    {
        using (var dc = new FooDataContext())
        {
            var euid = this.GetEffectiveUser().UID;
            var impersonation = dc.Table<Impersonation>()
                                  .Where( i => i.EffectiveUser == euid && i.ActualUser == currentUser.UniversityID && !i.EndTime.HasValue )
                                  .OrderByDescending( i => i.ID )
                                  .FirstOrDefault();

            if (impersonation != null)
            {
                impersonation.EndTime = DateTime.Now;
                dc.SubmitChanges();
            }
        }
    }
}

答案 1 :(得分:1)

由于ASP.NET成员资格使用cookie,因此我不知道有一个简单的程序化解决方案。但是,您可以让支持人员使用其他浏览器(例如IE和Firefox)登录。或者,如果您可以控制网站的设置,则可以为支持人员提供不同的网址:support.domain.comwww.domain.com,以便Cookie不同。

答案 2 :(得分:0)

最简单的解决方案是让客户支持人员在不同的浏览器中以客户身份登录-e.g.在IE中登录,但作为Chrome中的客户