Web Services 在401个错误后,使用C#调用Dynamics NAV Web服务成功

kyvafyod  于 2022-11-15  发布在  C#
关注(0)|答案(2)|浏览(252)

我遇到了一些奇怪的行为(意味着我不明白发生了什么),如果可能的话,我希望有人帮助我解决它。
我们有一些Dynamics 365 NAV Business Central Web服务通过SSL证书安全地公开,我们使用一些标准C#代码访问这些证书。
我们已经将SOAP代理添加到ASP.NETWebforms应用程序中,这一切都按预期工作。
然后,我们声明Web服务的示例,使用新的NetworkCredential示例设置凭据,并将Web服务设置为使用PreAuthenticate,然后调用服务上的方法。

public static bool CheckServiceStatus()
{
    bool returnValue = false;
    try
    {
        svcWebServiceServer webService = new svcWebServiceServer();
        webService.Credentials = new NetworkCredential(Globals.WebServiceUsername, Globals.WebServicePassword, Globals.WebServiceDomain);
        webService.PreAuthenticate = true;
        webService.FncServiceStatus(ref returnValue);
    }
    catch (Exception ex)
    {
        LoggingFunctions.WriteMessageToDisk("CheckServiceStatus error : " + ex.Message);
    }
    return returnValue;
}

当我们查看Fiddler中的日志时,我们看到服务被调用了两次。第一次调用时,我们得到一个401错误,它告诉我们必须使用NTLM,然后使用更长的NTLM密钥进行第二次调用,调用成功,我们得到了数据...
第一次尝试...

第二次......

有没有人能告诉我如何进行Web服务调用,以便它第一次进行身份验证?401被认为是DDOS风格的攻击,然后流量被阻止。
我尝试过更改凭据的传递方式,但这没有任何区别...

public static bool CheckServiceStatus()
{
    bool returnValue = false;
    try
    {
        svcWebServiceServer webService = new svcWebServiceServer();
        CredentialCache credCache = new CredentialCache();
        credCache.Add(new Uri(webService.Url), "NTLM", new NetworkCredential(Globals.WebServiceUsername, Globals.WebServicePassword, Globals.WebServiceDomain));
        webService.Credentials = credCache;
        webService.PreAuthenticate = true;
        webService.FncServiceStatus(ref returnValue);
    }
    catch (Exception ex)
    {
        LoggingFunctions.WriteMessageToDisk("CheckServiceStatus error : " + ex.Message);
    }
    return returnValue;
}
eivnm1vs

eivnm1vs1#

根据本文-https://learn.microsoft.com/en-gb/archive/blogs/chiranth/ntlm-want-to-know-how-it-works- NTLM以质询响应方式工作。
第一次呼叫Web服务时(即使您在credentialCache对象中指定NTLM),第一个请求似乎是匿名传送的。
然后服务器用401和一些WWW-Authenticate头来响应,这些头指定服务需要通过NTLM的身份验证详细信息。
然后,客户端(C#应用程序)发送一个包含NTLM标头的新请求,该标头包含一个表示用户名、计算机名和域的编码值。
服务器将请求传递给认证服务器,认证服务器生成一个挑战,并在另一个401响应中将其发送回客户端。
客户端收到挑战后,会根据挑战和密码计算杂凑值,并将其传回Web服务。验证服务器会将此杂凑值与自己的杂凑值进行比较,只要认证正确,便会通过验证,并传回200回应,沿着客户端最初进行Web服务呼叫的结果。
当我们在代码中添加PreAuthenticate = true时,我们只需在前面传递NTLM用户名、计算机名和域,跳过第一步。这将401的数量从2减少到1。
我并不自称是认证领域的Maven,但在阅读了上面链接的页面并进行了一些测试后,这是我们的发现。如果有人想评论/纠正我,请随意。
为了完整起见,我们已经开始调查Dynamics 265设置中的“UserName”身份验证方法,以访问Dynamics NAV 2018 Web服务,该方法将此身份验证传递给Dynamics NAV 365的控件,这意味着我们不会获得401。但是,我们现在无法在浏览器中访问Web服务,因为这使用了摘要,并且我们似乎无法通过浏览器进行身份验证。得到400个错误。

py49o6xq

py49o6xq2#

也许你必须把UseDefaultCredentials设置为false。这是我如何做的一个例子。但是,我没有用fiddler做检查:

NetworkCredential cred = new NetworkCredential(Globals.WebServiceUsername, Globals.WebServicePassword, Globals.WebServiceDomain);
svcWebServiceServer webService = new svcWebServiceServer();
webService.Timeout = Globals.Timeout;
webService.Url = Globals.Url;
webService.UseDefaultCredentials = false; // <-----
webService.Credentials = cred;

相关问题