Вы должны абстрагировать это на более высоком уровне, чем аутентифицированный пользователь. Я предлагаю вам представить концепцию зарегистрированного пользователя и текущего пользователя. Сеанс остается с вошедшим в систему пользователем, но вошедшие в систему пользователи с достаточными привилегиями имеют возможность выдавать себя за других пользователей, причем этот пользователь становится текущим пользователем. Использовать текущего пользователя для управления доступом к данным, управлять пользовательским интерфейсом (за исключением того, что пользователю, имитирующему себя, необходимо контролировать олицетворение), выполнять транзакции и т. Д. Сохранять текущего пользователя в сеансе в качестве данных, возможно, устанавливая часто используемые свойства в базовый контроллер в 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();
}
}
}
}