2011-12-05 3 views
1

현재 지원을 위해 고객 자체로 로그인하려면 "고객 지원"사용자가 필요한 웹 사이트를 구현하고 있습니다. 문제는 고객 사용자와의 로그인은 고객 지원 로그인을 방해하므로 단일 사용자 만 단일 컴퓨터에서 동시에 로그인 할 수 있다는 것입니다.AspNetSqlMembershipProvider를 여러 동시 세션에 사용하는 방법은 무엇입니까?

인증을 위해 MVC3을 AspNetSqlMembershipProvider와 함께 사용합니다.

한 대의 컴퓨터에서 여러 동시 로그인을 easly 사용할 수 있습니까?

답변

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(); 
      } 
     } 
    } 
} 
+0

꽤 괜찮은 멋진 솔루션이지만, 새로운 멤버십 공급자를 작성하는 실제 해결책에 대한 해결책이 아닌지 궁금합니다. 어떻게 생각해? –

+0

@EranBetzalel 여전히 인증을 위해 멤버 자격 공급자를 사용할 수 있습니다. 필자의 경우에는 싱글 사인온 (single sign-on)을 처리하기 위해 외부 인증 소스 (CAS)와 함께 사용됩니다. 로그인 된 사용자 대 운영자를 결정하는 데 사용됩니다. 또한 누가 보안을 위해 누가 가장하고 있는지 기록합니다. 기본 뷰 모델이 운영 사용자 (실제 사용자는 여전히 컨텍스트에서 발견됨)로 채워지는 비트를 생략했습니다. 이 기능의 한 가지 장점은 암호를 공유 할 필요가 없다는 것입니다. 지원 담당자는 다른 사람이 될 권리가 있습니다. – tvanfosson

+0

또한 MembershipProvider에는이를 지원하는 올바른 서명이 없다는 점에 유의하십시오. 여러분이 반환하는 사용자 객체는 IPrincipal 또는 IIdentity보다 훨씬 풍부한 엔티티 모델이라는 것을 알 수 있습니다. – tvanfosson

1

ASP.NET 멤버십이 쿠키를 사용하여 작동하기 때문에 내가 아는 간단한 프로그래밍 방식의 솔루션이 없습니다. 그러나 지원 담당자가 다른 브라우저 (예 : IE 및 Firefox)로 로그인하도록 할 수 있습니다. 또는 사이트 설정을 제어 할 수있는 경우 지원 담당자에게 support.domain.comwww.domain.com이라는 다른 URL을 제공하여 쿠키가 구분되도록 할 수 있습니다.

0

가장 쉬운 해결책은 고객 지원 사람들이 다른 브라우저 -e.g.의 고객으로 로그온에 도착하는 것 IE에서 자신은 Chrome에서 고객으로 로그온

관련 문제