he implementado un objeto personalizado del perfil en el código como se describe por Joel aquí:Usando membresía y perfil de ASP .NET con MVC, ¿cómo puedo crear un usuario y configurarlo en HttpContext.Current.User?
no puedo conseguir que funcione cuando estoy creando un nuevo usuario, sin embargo. Cuando hago esto:
Membership.CreateUser(userName, password);
Roles.AddUserToRole(userName, "MyRole");
el usuario se crea y se añade a un papel en la base de datos, pero HttpContext.Current.User
sigue vacío, y Membership.GetUser()
vuelve nula, por lo que este (a partir del código de Joel) no funciona:
static public AccountProfile CurrentUser
{
get { return (AccountProfile)
(ProfileBase.Create(Membership.GetUser().UserName)); }
}
AccountProfile.CurrentUser.FullName = "Snoopy";
he intentado llamar Membership.GetUser(userName)
y configuración de propiedades del perfil de esa manera, pero las propiedades de deformación permanecen vacías, y llamando AccountProfile.CurrentUser(userName).Save()
no ponga nada en la base de datos. También intenté indicar que el usuario es válido &, inicie sesión, llamando al Membership.ValidateUser
, FormsAuthentication.SetAuthCookie
, etc., pero el usuario actual sigue siendo nulo o anónimo (dependiendo del estado de las cookies de mi navegador).
RESUELTO (EDITADO MÁS ADELANTE, VEA A CONTINUACIÓN): Basado en la explicación de Franci Penov y un poco más de experimentación, descubrí el problema. El código de Joel y las variaciones que probé solo funcionarán con un perfil existente. Si no existe ningún perfil, ProfileBase.Create(userName)
devolverá un nuevo objeto vacío cada vez que se llame; puede establecer propiedades, pero no se "pegarán" porque se devuelve una nueva instancia cada vez que accede a ella. Configuración HttpContext.Current.User
a un nuevo GenericPrincipal
se le dará un objeto de usuario, pero no un objeto Perfil, y ProfileBase.Create(userName)
y HttpContext.Current.Profile
todavía apuntará a nuevos objetos, vacías.
Si desea crear un perfil para un usuario recién creado en la misma solicitud, debe llamar al HttpContext.Current.Profile.Initialize(userName, true)
. A continuación, puede completar el perfil inicializado y guardarlo, y estará accesible en solicitudes futuras por nombre, para que el código de Joel funcione. Estoy solo usando HttpContext.Current.Profile
internamente, cuando necesito crear/acceder al Perfil inmediatamente después de la creación. En cualquier otra solicitud, uso ProfileBase.Create(userName)
y expuse solo esa versión como pública.
Tenga en cuenta que Franci es correcta: si está dispuesto a crear el Usuario (y Roles) y establecerlo como Autenticado en el primer viaje de ida y vuelta, y le pide al usuario que inicie sesión, podrá acceder al Perfil mucho más simple a través del código de Joel en la solicitud posterior. Lo que me impresionó es que se puede acceder inmediatamente a Roles al crear el usuario sin ninguna inicialización, pero Profile no lo está.
Mi nuevo código AccountProfile:
public static AccountProfile CurrentUser
{
get
{
if (Membership.GetUser() != null)
return ProfileBase.Create(Membership.GetUser().UserName) as AccountProfile;
else
return null;
}
}
internal static AccountProfile NewUser
{
get { return System.Web.HttpContext.Current.Profile as AccountProfile; }
}
Nueva creación del usuario:
MembershipUser user = Membership.CreateUser(userName, password);
Roles.AddUserToRole(userName, "MyBasicUserRole");
AccountProfile.NewUser.Initialize(userName, true);
AccountProfile.NewUser.FullName = "Snoopy";
AccountProfile.NewUser.Save();
El acceso posterior:
if (Membership.ValidateUser(userName, password))
{
string name = AccountProfile.CurrentUser.FullName;
}
aún más gracias a Franci para explicar el ciclo de vida de autenticación - I' Estoy llamando a FormsAuthentication.SetAuthCookie en mi función de validación, pero estoy devolviendo un bo ol para indicar el éxito, porque User.Identity.IsAuthenticated no será verdadero hasta la solicitud posterior.
REVISADO: Soy un idiota. La explicación anterior funciona en el caso estrecho, pero no resuelve el problema de fondo: Llamada CurrentUser devuelve una nueva instancia del objeto cada vez, si se trata de un perfil existente o no. Debido a que se define como una propiedad, no estaba pensando en esto, y escribió:
AccountProfile.CurrentUser.FullName = "Snoopy";
AccountProfile.CurrentUser.OtherProperty = "ABC";
AccountProfile.CurrentUser.Save();
la que (por supuesto) no funciona. Debe ser:
AccountProfile currentProfile = AccountProfile.CurrentUser;
currentProfile.FullName = "Snoopy";
currentProfile.OtherProperty = "ABC";
currentProfile.Save();
Es mi propia culpa por pasar por alto por completo este punto básico, pero yo creo que se declara CurrentUser como una propiedad implica que se trata de un objeto que puede ser manipulada. En cambio, debe declararse como GetCurrentUser()
.
¿Este trabajo por hacerse pasar por otro usuario, así? –
suplantación por lo general implica la autenticación de Windows, lo que requiere un WindowsPrincipal. La suplantación se puede hacer desde el token de seguridad para el usuario suplantado o desde las credenciales. Dado que el contexto actual no está autenticado, es probable que no haya forma de obtener un token de seguridad para el usuario. Por lo tanto, las únicas opciones son suplantar con credenciales. Podría ser posible construir un WindowsPrincipal con la identidad correcta llamando LogonUser (siempre que el código conoce las credenciales para el usuario de Windows). Sin embargo, no lo he intentado, así que no puedo garantizar que funcione necesariamente. –
Esa es una explicación increíblemente útil, gracias.Crear un GenericPrincipal (desde mi FormsAuthenticationTicket) me permitió establecer HttpContext.Current.User. Sin embargo, todavía no puedo establecer los valores del perfil. Si uso ProfileBase.Create (Membership.GetUser(). UserName) .SetPropertyValue, no ocurre nada, ya no arroja una excepción, pero la propiedad permanece vacía. Si uso HttpContext.Current.Profile.SetPropertyValue, dice que no puedo establecer propiedades en un perfil anónimo, lo que implica que estos son diferentes objetos de perfil que de alguna manera tengo que fusionar. –