Pergunta

Eu tenho um relatório salvo em um servidor de relatórios SQL2005, e quero retornar um PDF processado deste relatório. Eu descobri isso quando se trabalha com um arquivo .rdlc * local ( e eu tenho um blog sobre isso ), mas não quando reside * .rdl em um servidor de relatórios. Estou recebendo um 401 Não autorizado Erro na linha ...

reportViewer.ServerReport.SetParameters(reportDefinition.ReportParameters);

Aqui está o método utilizado para processar o relatório.

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

A outra coisa que está faltando é a 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);
    }
}

Outras coisas que você pode precisar de saber ...

  • Este está sendo executado em uma intranet, e a representação estiver activada.
  • Registro indica que o usuário representação está sendo definido corretamente.
  • Este funciona quando executado no Visual Studio (http://localhost:devport), e funciona quando em execução no meu caixa de desenvolvimento (http://localhost/myApplication). É não funciona quando executado em nossos servidores de teste ou de produção.
  • Eu tentei soluções com e sem configurações system.net.defaultProxy em web.config. Nem funcionou.

O que estou fazendo de errado? É uma configuração do servidor? É código? É web.config?

Foi útil?

Solução

Nós fez finalmente descobrir o problema. Nossos administradores de rede têm desativado double-hopping, por isso, enquanto a representação foi corretamente conectando como domain\jmeyer, o aplicativo ainda estava tentando se conectar à caixa de SRS com domain\web01$. Por que é configurado como este? Porque double-hopping é uma falha de segurança enorme. (Ou assim me foi dito. Isso soa como algo que você leria sobre The Daily WTF ?)

A nossa solução foi criar um usuário domain\ssrs_report_services genérico, e se conectar com o usuário com as seguintes credenciais de rede

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

A descrição acima é o exemplo solução clássica que você pode encontrar tudo sobre os internets.

Outras dicas

"Double pulando" é permitido - (! Contanto que ele está funcionando corretamente) swith a autenticação Kerberos ...

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top