且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

在.NET Core中针对ReportExecution2005.asmx进行身份验证

更新时间:2023-11-30 23:20:46

经过一天的努力,我发现使用唯一的构造方法似乎可行不会立即调用问题中指出的ConfigureEndpoint。如果我创建了一个指定NTLM的绑定,并将该绑定与手动创建的端点一起传递,则它会起作用:

  var绑定= new BasicHttpBinding(BasicHttpSecurityMode.TransportCredentialOnly)
{
Security =
{
Transport = new HttpTransportSecurity {ClientCredentialType = HttpClientCredentialType.Ntlm}
}
};

var reportService = new CssbiReportService.ReportExecutionServiceSoapClient(binding,
new EndpointAddress( http://myserver/ReportServer/ReportExecution2005.asmx));

这在.NET Core中对我有用。


I'm trying to execute an s-s-rS report in .NET Core.

Since .NET Core doesn't let you add service references, you have to use the WCF Connected Service to add a reference to the WSDL so it can generate .NET Core compatible code. This is what I did for ReportExecution2005.asmx (SQL Server 2016 if it matters).

I tried using the following to authenticate against the service:

var rsExec = new ReportExecutionServiceSoapClient(ReportExecutionServiceSoapClient.EndpointConfiguration.ReportExecutionServiceSoap,
                                                  new EndpointAddress("http://server/ReportServer/ReportExecution2005.asmx"))
                    {
                        ClientCredentials =
                        {
                            Windows =
                            {
                                AllowedImpersonationLevel = TokenImpersonationLevel.Impersonation,
                                ClientCredential = new NetworkCredential("username", "password")
                            }
                        }
                    };

Also tried setting the Username object instead of Windows object, but either way the result is the following error:

MessageSecurityException: The HTTP request is unauthorized with client authentication scheme 'Anonymous'. The authentication header received from the server was 'NTLM'.

Looking at Fiddler, the code isn't passing the credentials along.

This is the code that got generated off the WSDL

public ReportExecutionServiceSoapClient(EndpointConfiguration endpointConfiguration, System.ServiceModel.EndpointAddress remoteAddress)
   : base(ReportExecutionServiceSoapClient.GetBindingForEndpoint(endpointConfiguration), remoteAddress)
{
    this.Endpoint.Name = endpointConfiguration.ToString();
    ConfigureEndpoint(this.Endpoint, this.ClientCredentials);
}

static partial void ConfigureEndpoint(System.ServiceModel.Description.ServiceEndpoint serviceEndpoint, System.ServiceModel.Description.ClientCredentials clientCredentials);

I may be mistaken, but isn't this calling the private method ConfigureEndpoint with the ClientCredentials object before the ClientCredentials object has even been set?

I'm not seeing any other way to configure the ClientCredentials or call ConfigureEndpoint, so how exactly are you supposed to authenticate? The other constructors are basically the same thing, except for one which takes in a Binding instead of an EndpointConfiguration. Any ideas?

After fighting with this for a day, I found an approach that seems to work, by using the only constructor that does not immediately call ConfigureEndpoint as pointed out in the question. If I create a binding that specifies NTLM, and I pass that binding along with a manually created endpoint, it works:

var binding = new BasicHttpBinding(BasicHttpSecurityMode.TransportCredentialOnly)
{
    Security =
    {
        Transport = new HttpTransportSecurity {ClientCredentialType = HttpClientCredentialType.Ntlm}
    }
};

var reportService = new CssbiReportService.ReportExecutionServiceSoapClient(binding,
    new EndpointAddress("http://myserver/ReportServer/ReportExecution2005.asmx"));

This is working for me in .NET Core.