2009-09-17 21 views
7

Mam raport zapisany na serwerze raportującym SQL2005 i chcę zwrócić wyrenderowany plik PDF tego raportu. Stwierdziłem to podczas pracy z lokalnym plikiem * .rdlc (and I've blogged about it), ale nie wtedy, gdy * .rdl znajduje się na serwerze raportowania. Otrzymuję 401 niedopuszczonych błąd na linii ...Przeglądarka raportów SSRS + Poświadczenia ASP.NET 401 Wyjątek

reportViewer.ServerReport.SetParameters(reportDefinition.ReportParameters); 

Oto metoda stosowana do renderowania raportu.

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

Kolejną rzeczą, której brakuje, jest klasa 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); 
    } 
} 

Inne rzeczy może trzeba wiedzieć ...

  • To jest uruchomiony w intranecie i personifikacji jest włączona.
  • Rejestrowanie wskazuje, że użytkownik podszywania się jest ustawiony prawidłowo.
  • Ten działa podczas pracy w Visual Studio (http://localhost:devport), a działa gdy działa na moim komputerze rozwoju (http://localhost/myApplication). To nie działa podczas pracy na naszych testowych lub produkcyjnych serwerach.
  • Próbowałem rozwiązań zarówno zi bez system.net.defaultProxy ustawienia w web.config. Żaden nie zadziałał.

Co robię źle? Czy to ustawienie serwera? Czy to kod? Czy to jest web.config?

+0

Czy użytkownik personifikacji mieć dostęp do serwera raportu - tego sprawozdania, w szczególności? – NYSystemsAnalyst

+0

Czy próbowałeś używać IIS pod użytkownikiem podszywania się na swoim komputerze (localhost), aby dokładniej emulować to, co dzieje się na serwerze testowym? Wygląda na to, że z użytkownikiem podszywającym się na serwer raportowania lub bazę danych serwera raportowania powstaje problem z zezwoleniami. Zakładam, że użytkownik podszywania się jest kontem domeny. –

+0

@NYSystemsAnalyst - Tak, użytkownik podszywania się ma dostęp do odpowiedniego katalogu na serwerze raportów. –

Odpowiedz

5

W końcu udało nam się rozwiązać problem. Nasi administratorzy sieci wyłączyli podwójne przeskakiwanie, więc podczas gdy personifikacja poprawnie łączyła się pod numerem domain\jmeyer, aplikacja nadal próbowała połączyć się z polem SRS pod numerem domain\web01$. Dlaczego jest skonfigurowany w ten sposób? Ponieważ podwójne przeskoki to ogromna luka w zabezpieczeniach. (Przynajmniej tak mi powiedziano. Czy to brzmi jak coś, co można przeczytać na The Daily WTF?)

Nasze rozwiązanie było stworzenie rodzajowe domain\ssrs_report_services użytkownika i połączyć się z tym użytkownikiem z następujących poświadczeń sieciowych

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

Powyższe jest klasycznym przykładem rozwiązania, które można znaleźć w całym Internecie.

+0

W rzeczywistości, nie sądzę, podwójne hopping jest "dozwolone" w dowolnej konfiguracji. Nie jest dla mnie jasne, dlaczego środowisko programistyczne działało, ale prawdopodobnie zostało skonfigurowane inaczej. –

+0

Jak mi wyjaśniono, działa na dev, ponieważ nie liczy się jako hop od localhost (jako klienta) -> localhost (jako IIS) -> SRS –

+0

FYI, administratorzy mogą konfigurować delegację na na podstawie serwera. Sprawdź: http://serverfault.com/questions/16364/is-there-a-way-to-get-kerberos-credentials-to-delegate-twice-why-not –

2

„Double Hopping” jest dozwolone - Swith uwierzytelniania Kerberos ... (tak długo, jak to działa prawidłowo!)

+1

Niestety, my, deweloperzy, jesteśmy ograniczeni przez środowisko i nie mamy nic wspólnego z infrastrukturą. Dziękuję, że dałeś mi coś nowego do przeczytania. –

Powiązane problemy