2009-09-17 18 views
7

Tengo un informe guardado en un servidor de informes SQL2005 y deseo devolver un PDF renderizado de este informe. Lo he descubierto al trabajar con un archivo local * .rdlc (and I've blogged about it), pero no cuando el * .rdl reside en un servidor de informes. Estoy recibiendo un error de 401 no autorizado en la línea ...Visor de informes SSRS + credenciales ASP.NET 401 Excepción

reportViewer.ServerReport.SetParameters(reportDefinition.ReportParameters); 

Aquí es el método utilizado para representar el informe.

public byte[] Render(IReportDefinition reportDefinition) 
{ 
    var reportViewer = new ReportViewer(); 
    byte[] renderedReport; 
    try 
    { 
     var credentials = new WindowsImpersonationCredentials(); 
     reportViewer.ServerReport.ReportServerUrl = new Uri("http://myssrsbox", UrlKind.Absolute); 
     reportViewer.ServerReport.ReportServerCredentials = credentials; 
     reportViewer.ServerReport.ReportPath = reportDefinition.Path; 
     // Exception is thrown on the following line... 
     reportViewer.ServerReport.SetParameters(reportDefinition.ReportParameters); 

     string mimeType; 
     string encoding; 
     string filenameExtension; 
     string[] streams; 
     Warning[] warnings; 

     renderedReport = reportViewer.ServerReport.Render(reportDefinition.OutputType, reportDefinition.DeviceInfo, out mimeType, out encoding, out filenameExtension, out streams, out warnings); 
    } 
    catch (Exception ex) 
    { 
     // log the error... 
     throw; 
    } 
    finally 
    { 
     reportViewer.Dispose(); 
    } 
    return renderedReport; 
} 

La otra cosa que te falta es la clase WindowsImpersonationCredentials.

public class WindowsImpersonationCredentials : IReportServerCredentials 
{ 
    public bool GetFormsCredentials(out Cookie authCookie, out string userName, out string password, out string authority) 
    { 
     authCookie = null; 
     userName = password = authority = null; 
     return false; 
    } 

    public WindowsIdentity ImpersonationUser 
    { 
     get { return WindowsIdentity.GetCurrent(); } 
    } 

    public ICredentials NetworkCredentials 
    { 
     get { return null; } 
    } 

    public override string ToString() 
    { 
     return String.Format("WindowsIdentity: {0} ({1})", this.ImpersonationUser.Name, this.ImpersonationUser.User.Value); 
    } 
} 

Otras cosas que usted puede necesitar saber ...

  • Esto se está ejecutando en una intranet, y se activa la suplantación.
  • El registro indica que el usuario de suplantación se está configurando correctamente.
  • Este Cómo funciona cuando se ejecuta en Visual Studio (http://localhost:devport), y Cómo funciona cuando se ejecuta en mi máquina de desarrollo (http://localhost/myApplication). Es no funciona cuando se ejecuta en nuestros servidores de prueba o producción.
  • He intentado soluciones con y sin system.net.defaultConfiguraciones de proxy en web.config. Ninguno funcionó.

¿Qué estoy haciendo mal? ¿Es una configuración de servidor? ¿Es código? ¿Es web.config?

+0

¿El usuario suplantación tienen acceso al servidor de informes - ese informe en particular? – NYSystemsAnalyst

+0

¿Ha intentado ejecutar IIS bajo el usuario de suplantación en su máquina de desarrollo (localhost) para emular más de cerca lo que está sucediendo en su servidor de prueba? Suena como un problema de permisos sin inconvenientes con su usuario de suplantación contra el servidor de informes o la base de datos del servidor de informes. Supongo que el usuario de suplantación es una cuenta de dominio. –

+0

@NYSystemsAnalyst - Sí, el usuario de suplantación tiene acceso al directorio apropiado en el servidor de informes. –

Respuesta

5

Finalmente descubrimos el problema. Nuestros administradores de red han desactivado el doble salto, por lo que, aunque la suplantación se conectó correctamente como domain\jmeyer, la aplicación todavía estaba intentando conectarse al cuadro de SRS con domain\web01$. ¿Por qué está configurado así? Porque el doble salto es un agujero de seguridad masivo. (O al menos eso me dijeron. ¿Suena esto como algo que se leería en The Daily WTF?)

Nuestra solución fue crear un domain\ssrs_report_services usuario genérico, y conectarse con ese usuario con las siguientes credenciales de red

public class CustomCredentials : IReportServerCredentials 
{ 
    public bool GetFormsCredentials(out Cookie authCookie, out string userName, out string password, out string authority) 
    { 
     authCookie = null; 
     userName = password = authority = null; 
     return false; 
    } 

    public WindowsIdentity ImpersonationUser 
    { 
     get { return null; } 
    } 

    public ICredentials NetworkCredentials 
    { 
     get { return new NetworkCredential("ssrs_report_services", "password", "domain") ; } 
    }  
} 

Lo anterior es la solución clásica de ejemplo que puedes encontrar en todos los internets. está permitido

+0

De hecho, no creo que el doble salto esté "permitido" en ninguna configuración. No me queda claro por qué su entorno de desarrollo estaba funcionando, pero probablemente se configuró de manera diferente. –

+0

Como se me explicó, funciona en dev porque no cuenta como un salto para ir desde localhost (como cliente) -> localhost (como IIS) -> SRS –

+0

FYI, los administradores pueden configurar la delegación en un servidor base Consulte: http://serverfault.com/questions/16364/is-there-a-way-to-get-kerberos-credentials-to-delegate-twice-why-not –

2

"salto doble" - swith en la autenticación Kerberos ... (con tal de que está funcionando correctamente!)

+1

Desafortunadamente, los desarrolladores estamos limitados por el entorno y no tenemos voz en la infraestructura. Sin embargo, gracias por darme algo nuevo sobre lo que leer. –

Cuestiones relacionadas