impersonation

21/10/2009 - 09:46 por josetellan | Informe spam
Hola a todos, les cuento el problema.
tengo una feature que sube en cada sitio creado una serie de masterpages y
aplica un tema determinado en funcion de la aplicacion en la que se crea
dicho sitio. las masterpages son para las paginas de contenido y tambien para
las paginas de administracion (/layouts). el cambio de masterpage lo hago a
traves de un httpmodule que segun que pagina se pida al servidor me pone una
master u otra. esa es la funcionalidad de mi codigo y todo lo hace genial
pero le falta lo mas importante. como la creacion de sitios debe ser con un
usuario con los permisos adecuados, adjunte un archivo de configuracion a la
feature llamado "siteConfigurator.config", desde el que leo un tag
<impersonate> con el user y pass del admin de la granja sin encriptar ni
nadapero como estaba en desarrollo pues me valia hasta lograr la
funcionalidad.
esos 3 valores (domain, user y pass) se le pasan a un metodo de una clase
llamada "impersonation.cs" que tiene este codigo:

public class Impersonation
{
public const int LOGON32_LOGON_INTERACTIVE = 2;
public const int LOGON32_PROVIDER_DEFAULT = 0;
private WindowsIdentity tempWindowsIdentity;


WindowsImpersonationContext impersonationContext;

[DllImport("advapi32.dll")]
public static extern int LogonUserA(String lpszUserName,
String lpszDomain,
String lpszPassword,
int dwLogonType,
int dwLogonProvider,
ref IntPtr phToken);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError =
true)]
public static extern int DuplicateToken(IntPtr hToken,
int impersonationLevel,
ref IntPtr hNewToken);

[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError =
true)]
public static extern bool RevertToSelf();

[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern bool CloseHandle(IntPtr handle);

internal bool ImpersonateValidUser(String userName, String domain,
String password)
{
//WindowsIdentity tempWindowsIdentity;
IntPtr token = IntPtr.Zero;
IntPtr tokenDuplicate = IntPtr.Zero;

if (RevertToSelf())
{
if (LogonUserA(userName, domain, password,
LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT, ref token) != 0)
{
if (DuplicateToken(token, 2, ref tokenDuplicate) != 0)
{
tempWindowsIdentity = new
WindowsIdentity(tokenDuplicate);
impersonationContext =
tempWindowsIdentity.Impersonate();
if (impersonationContext != null)
{
CloseHandle(token);
CloseHandle(tokenDuplicate);
return true;
}
}
}
}


if (token != IntPtr.Zero)
CloseHandle(token);
if (tokenDuplicate != IntPtr.Zero)
CloseHandle(tokenDuplicate);
return false;
}

internal void UndoImpersonation()
{
impersonationContext.Undo();
}
}

la funcion nos devuelve true si el token es valido. mi pregunta escual
es la mejor manera ( donde colocarlos, como recogerlos y como pasarlos) de
recoger los valores de domain , user y pass para pasarselos a esta clase



les cuento lo que he probado hasta ahora:

en primer lugar lei el tema de "aspnet_regiis -pe ." para encriptar
secciones de web.config ´s...y lo hacia genial pero no se por qué las
busquedas dejaban de funcionar y como las busquedas son tan importantes en la
intranet de mi empresa pues se ha decidio combiar de estrategia. y en segundo
lugar probe a insertar el codigo referente a runwithelevatedprivileges pero
me da algunos errores que me hacen preguntarme si voy por el buen camino.

muchas gracias de antemano y un saludo.

Preguntas similare

Leer las respuestas

#6 David Martos
26/10/2009 - 19:53 | Informe spam
Hola José,

lo siento pero me he perdido por completo con tu explicación. Para probar
usuarios concurrentes tienes muchas herramientas. Te recomiendo Visual
Studio Team System, pero seguro que tienes otras por ahí que puedes utilizar
para hacer tests de carga.

Respecto a lo que he entendido... yo no cambiaría la página maestra de las
páginas de _layouts, que es lo que me ha parecido. Sólo cambiaría aquellas
que puedes cambiar con el UI de MOSS. En ese caso, los cambios los haces a
nivel de site collection, con lo que no necesitarías nada, según entiendo.
En cuanto a las páginas de _layouts, me da la sensación de que, al ser
compartidas por todas las web applications, quieres que, por ejemplo,
accediendo a:

http://webapplication1/_layouts/settings.aspx (verde)
http://webapplication2/_layouts/settings.aspx (blanco)
http://webapplication3/_layouts/settings.aspx (blanco)

la interfaz cambie según los colores de las 3 web applications. Si es esto
lo que intentas, plantéate que pasa si tenemos 2 usuarios, el primero accede
al primero de los enlaces (verde) y el segundo al segundo enlace,
simultaneamente. Suponiendo que se pueda realizar, estás accediendo al
fichero físico 12/TEMPLATE/LAYOUTS/settings.aspx dos veces para modificarlo.
Además, siendo un httpmodule, cada vez que refresques la página, realizarás
el cambio. Si encima tienes más de un frontend... lo tendrías que hacer en
todos los servidores.

Saludos,
David Martos
http://david-martos.blogspot.com


"josetellan" wrote in message
news:


"David Martos" wrote:

Hola José,

Otra opción que tienes es poner tu código dentro de un bloque
privilegiado:

http://msdn.microsoft.com/en-us/lib...leges.aspx

esto te permitirá crear los sitios con las credenciales del administrador
de
la colección de sitios sin tener que guardarlas en ningún sitio.

Por otro lado, comentas que usas un httpmodule para cambiar la masterpage
en
cada petición. ¿Esto te funciona bien con usuarios concurrentes? ¿Y en
cuanto al rendimiento? Yo no lo veo muy claro, porque estás haciendo una
modificación que afecta a todos los usuarios en cada una de las
peticiones.
Si necesitase mostrar algo diferente en base al usuario, haría uso de
audiencias, de controles web (o de webparts) y, en última instancia, de
variaciones de sitio.

Saludos,
David Martos
http://david-martos.blogspot.com


Hola David, graci9as por el aporte del codigo privilegiado, ahora mismo me
pongo con elloya lo contare aqui en el foro.


Respecto a lo del httpmodulesegun dices que el rendimiento puede estar
un poco fastidiado no???.como puedo hacer una prueba para comprobar lo
que dices de usuarios concurrentes???
de todas formas te explico un poco mas en detalle.

Se tienen 3 web application y en la que una de ellas es de apariencia
blanca
y las otras dos son verdes. Tanto para las paginas que llevan asociadas la
default.master como para las que llevan la application.master tengo que
cambiarlas y ponerle las que corresponda en funcion de la application que
se
pida. Pero aqui entran siteCollections en los que estan aparte y no se les
debe poner ninguna master o a veces hay que ponerle otra distinta. Con lo
cual se tienen una serie de condiciones que hacen que el metodo elegido de
un
httpmodule mirando cada peticion sea el escogido...pero supongo que habra
otras alternativasasi que no va por usuarios sino por sitesCollections
y
applications...
No se si lo he dejado mas claro, espero que si, jejejje

Respuesta Responder a este mensaje
#7 josetellan
27/10/2009 - 07:54 | Informe spam
Hola David, efectivamernte eso es lo que hago, pero no tengo ningun problema
de rendimiento. ademas, hemos corrido un test de carga y sale todo bastante
bien. todavia no he podido hacer el codigo impersonadoa lo largo de la
mañana lo cuento aqui en el foro.
graciassssssssssssssss
Respuesta Responder a este mensaje
#8 josetellan
27/10/2009 - 08:27 | Informe spam
Hola Hans, voy a hacer el tema de la impersonation de las 2 formas que se me
han aconsejadola tuya y la del codigo privilegiado.
sobre tu solucion de encriptar el web.config de
c:\inetpub\wwwroot\wss\virtualdirectories\[puerto de tu aplicación web] . ¿lo
encriptas por aspnet_regiis o por algun otro metodo? y ¿Como recoges los
valores desde el code behind?

muchas gracias hans.
Respuesta Responder a este mensaje
#9 josetellan
27/10/2009 - 14:35 | Informe spam
Hola Hans y David,
ya lo he conseguido. Os cuento cómo:
en el code behind tengo esto

private System.Configuration.Configuration configIdentity =
System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration("/appName");
System.Web.Configuration.IdentitySection section =
(System.Web.Configuration.IdentitySection)configIdentity.GetSection("system.web/identity");

//y luego se recogen los valores...el user sale como domain\user ...substrings
User = section.UserName.ToString().Substring(12, 7);
Domain = section.UserName.ToString().Substring(0, 11);
Password = section.Password.ToString();

//y los usamos
impersonation.ImpersonateValidUser(User, Domain, Password);

Y en el web.config del inetpub de la aplicacion tengo esto otro:
<identity impersonate="false" userName="domain/user" password="xxx" />

lo que os llamara la atencion es el atributo impersonate=false no?...pues si
lo pongo a true no funciona, vamos, al depurar sale con valores null tanto el
user como el password y peta en la llamada a ImpersonateValidUser()

He encriptado la seccion identity del web.config con "aspnet_regiis -pef "

¿Que opinais sobre el atributo impersonate=false?

Muchas gracias y saludos.
Respuesta Responder a este mensaje
#10 David Martos
27/10/2009 - 20:35 | Informe spam
Hola,

si pones impersonate=true lo que haces es ejecutar el código en el contexto
del usuario que está autenticado en el sistema, por eso no te funciona. No
sé por qué username te sale a null (igual es el comportamiento por defecto)
pero entiendo que el password te salga a null, puesto que si no fuese así
sería bastante grave a nivel de seguridad (podrías obtener todos los
passwords de los usuarios que se conectasen a tu sistema con una línea de
código).

Sigo pensando que te sería más sencillo ejecutar el
SPSecurity.RunWithElevatedPrivileges. Los cambios en el web.config siempre
son delicados, sobretodo a nivel de despliegue en más de un entorno pero, si
te funciona así y no tienes problemas de despliegue, adelante :)

Saludos,
David Martos
http://david-martos.blogspot.com


"josetellan" wrote in message
news:
Hola Hans y David,
ya lo he conseguido. Os cuento cómo:
en el code behind tengo esto

private System.Configuration.Configuration configIdentity > System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration("/appName");
System.Web.Configuration.IdentitySection section > (System.Web.Configuration.IdentitySection)configIdentity.GetSection("system.web/identity");

//y luego se recogen los valores...el user sale como domain\user
...substrings
User = section.UserName.ToString().Substring(12, 7);
Domain = section.UserName.ToString().Substring(0, 11);
Password = section.Password.ToString();

//y los usamos
impersonation.ImpersonateValidUser(User, Domain, Password);

Y en el web.config del inetpub de la aplicacion tengo esto otro:
<identity impersonate="false" userName="domain/user" password="xxx"
/>

lo que os llamara la atencion es el atributo impersonate=false no?...pues
si
lo pongo a true no funciona, vamos, al depurar sale con valores null tanto
el
user como el password y peta en la llamada a ImpersonateValidUser()

He encriptado la seccion identity del web.config con "aspnet_regiis -pef
"

¿Que opinais sobre el atributo impersonate=false?

Muchas gracias y saludos.

Respuesta Responder a este mensaje
Ads by Google
Help Hacer una preguntaSiguiente AnteriorRespuesta Tengo una respuesta
Search Busqueda sugerida