2009-09-17 1 views
7

Ho un report salvato su un server di report SQL2005 e voglio restituire un PDF renderizzato di questo report. Ho capito questo quando si lavora con un file * .rdlc locale (and I've blogged about it), ma non quando il * .rdl risiede su un server di report. Sto ottenendo un 401 non autorizzato errore alla linea di ...Visualizzatore report SSRS + credenziali ASP.NET 401 Eccezione

reportViewer.ServerReport.SetParameters(reportDefinition.ReportParameters); 

Ecco il metodo utilizzato per il rendering del report.

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; 
} 

L'altra cosa che ti manca è la classe 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); 
    } 
} 

Altre cose potrebbe essere necessario sapere ...

  • Questo è in esecuzione su una rete Intranet, e rappresentazione è attivata.
  • La registrazione indica che l'utente di rappresentazione è stato impostato correttamente.
  • Questo funziona durante l'esecuzione in Visual Studio (http://localhost:devport), ed è funziona quando si esegue sulla mia casella di sviluppo (http://localhost/myApplication). È non funziona quando è in esecuzione sui nostri server di test o di produzione.
  • Ho provato soluzioni con e senza impostazioni system.net.defaultProxy in web.config. Nessuno dei due ha funzionato.

Cosa sto sbagliando? È un'impostazione del server? È un codice? È web.config?

+0

fa l'utente rappresentazione hanno accesso al server di report - che la relazione in particolare? – NYSystemsAnalyst

+0

Hai provato a eseguire IIS con l'utente di rappresentazione sulla tua macchina di sviluppo (localhost) per emulare più da vicino ciò che sta accadendo sul tuo server di prova? Sembra un problema di autorizzazioni flat out con il tuo utente di rappresentazione rispetto al server di report o al database del server di report. Presumo che l'utente di rappresentazione sia un account di dominio. –

+0

@NYSystemsAnalyst - Sì, l'utente di rappresentazione ha accesso alla directory appropriata sul server di report. –

risposta

5

Abbiamo finalmente capito il problema. I nostri amministratori di rete hanno disabilitato il doppio salto, quindi mentre la rappresentazione si collegava correttamente come domain\jmeyer, l'applicazione stava ancora tentando di connettersi alla casella SRS con domain\web01$. Perché è impostato in questo modo? Perché il doppio salto è un enorme buco di sicurezza. (O almeno così mi è stato detto. Questo suona come qualcosa che avrebbe letto sul The Daily WTF?)

La nostra soluzione era quella di creare un generico domain\ssrs_report_services utente, e connettersi con l'utente con le seguenti credenziali di rete

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") ; } 
    }  
} 

Quanto sopra è la classica soluzione di esempio che puoi trovare su tutti i canali.

+0

In effetti, non credo che il doppio salto sia "consentito" in qualsiasi configurazione. Non mi è chiaro perché il tuo ambiente di sviluppo funzionasse, ma probabilmente era configurato diversamente. –

+0

Come mi è stato spiegato, funziona su dev perché non conta come un salto da localhost (come client) -> localhost (come IIS) -> SRS –

+0

FYI, gli amministratori possono configurare la delega su un base del server. Controlla: http://serverfault.com/questions/16364/is-there-a---to-get-kerberos-credentials-to-delegate-twice-why-not –

2

"Double Hopping" è consentito - swith autenticazione Kerberos ... (finché funziona correttamente!)

+1

Sfortunatamente, noi sviluppatori siamo limitati dall'ambiente e non abbiamo voce in capitolo sull'infrastruttura. Grazie per avermi dato qualcosa di nuovo da leggere, comunque. –