2009-09-17 5 views
7

Ich habe einen Bericht auf einem SQL2005-Berichtsserver gespeichert und möchte eine gerenderte PDF-Datei dieses Berichts zurückgeben. Ich habe das bei der Arbeit mit einer lokalen * .rdlc-Datei (and I've blogged about it) herausgefunden, aber nicht, wenn sich die * .rdl auf einem Berichtsserver befindet. Ich erhalte einen 401 nicht autorisiert Fehler an der Linie ...SSRS-Berichtsanzeige + ASP.NET-Anmeldeinformationen 401 Ausnahme

reportViewer.ServerReport.SetParameters(reportDefinition.ReportParameters); 

Hier ist die Methode verwendet, um den Bericht zu machen.

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

Die andere Sache, die Sie vermissen, ist die Klasse 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); 
    } 
} 

Andere Dinge, die Sie wissen müssen ...

  • Dieses in einem Intranet ausgeführt wird, und Identitätswechsel aktiviert ist.
  • Die Protokollierung zeigt an, dass der Identitätswechselbenutzer ordnungsgemäß eingerichtet wurde.
  • Diese funktioniert, wenn in Visual Studio (http://localhost:devport) ausgeführt wird, und es funktioniert, wenn auf meinem Entwicklungsfeld (http://localhost/myApplication) ausgeführt wird. Es funktioniert nicht wenn auf unseren Test- oder Produktionsservern ausgeführt wird.
  • Ich habe versucht Lösungen mit und ohne system.net.defaultProxy Einstellungen in web.config. Keine funktionierte.

Was mache ich falsch? Ist es eine Servereinstellung? Ist es Code? Ist es web.config?

+0

Hat der Identitätswechsel Benutzer hat Zugriff auf den Berichtsserver - dieser Bericht insbesondere? – NYSystemsAnalyst

+0

Haben Sie versucht, IIS unter dem Identitätswechsel-Benutzer auf Ihrem Dev-Computer (localhost) auszuführen, um näher zu emulieren, was auf Ihrem Testserver passiert? Es klingt wie ein Problem mit dem Identitätswechsel mit dem Identitätswechsel-Benutzer gegenüber dem Berichtsserver oder der Berichtsserver-Datenbank. Ich nehme an, der Identitätswechsel-Benutzer ist ein Domänenkonto. –

+0

@NYSystemsAnalyst - Ja, der Identitätswechselbenutzer hat Zugriff auf das entsprechende Verzeichnis auf dem Berichtsserver. –

Antwort

5

Wir haben endlich das Problem herausgefunden. Unsere Netzwerkadministratoren haben das Double-Hopping deaktiviert. Während also der Identitätswechsel korrekt als domain\jmeyer verbunden war, versuchte die Anwendung weiterhin, eine Verbindung zur SRS-Box mit domain\web01$ herzustellen. Warum ist es so eingerichtet? Weil Double-Hopping ein massives Sicherheitsloch ist. (Oder so wurde ich gesagt. Klingen wie etwas, das Sie auf The Daily WTF lesen würden?)

Unsere Lösung einen generischen domain\ssrs_report_services Benutzer zu erstellen war, und eine Verbindung mit diesem Benutzer mit den folgenden Netzwerk-Anmeldeinformationen

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

Das oben genannte ist die klassische Beispiellösung, die Sie überall im Internet finden können.

+0

Tatsächlich glaube ich nicht, dass Doppel-Hopping in irgendeiner Konfiguration erlaubt ist. Es ist mir nicht klar, warum deine Entwicklungsumgebung funktionierte, aber es wurde wahrscheinlich anders konfiguriert. –

+0

Wie es mir erklärt wurde, funktioniert es auf dev, weil es nicht als Sprung von localhost (als Client) gilt -> localhost (als IIS) -> SRS –

+0

FYI, die Admins können Delegation auf einem per konfigurieren Serverbasis. Check out: http://serverfault.com/questions/16364/is-there-a-way-to-get- kerberos-credentials-to-delegate-twice-why-not –

2

„Double-Hopping“ erlaubt - swith auf dem Kerberos-Authentifizierung ... (so lange, wie es richtig funktioniert!)

+1

Leider sind wir Entwickler durch die Umgebung ziemlich eingeschränkt und haben kein Mitspracherecht in der Infrastruktur. Danke, dass du mir etwas Neues gegeben hast. –