HttpWebRequest未传递凭据

33

我正在尝试使用HTTPWebRequest访问REST服务,但是在传递凭证方面遇到了问题,请参见下面的代码。我已经阅读了NetworkCredential不支持SSL,并且我正在访问一个HTTPS站点。是否有人知道类似于NetworkCredential但支持SSL的类?

Uri requestUri = null;
Uri.TryCreate("https://mywebserver/webpage", UriKind.Absolute, out requestUri);
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(requestUri);
NetworkCredential nc = new NetworkCredential("user", "password");
request.Credentials = nc;
request.Method = WebRequestMethods.Http.Get;
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
4个回答

49

看看是否可以使用老式方法找到它:

string credentials = Convert.ToBase64String(ASCIIEncoding.ASCII.GetBytes("user"+ ":" + "password"));
request.Headers.Add("Authorization", "Basic " + credentials);

3
你能否解释一下为什么这个会起作用而 NetworkCredentials 不会? - Riaan van Zyl

28
什么样的身份验证机制保护了Web服务?设置在HttpWebRequest上的凭据只会通过BasicDigestNTLM的HTTP Authorization标头传递。因此,如果您的Web服务受到WS-Security的保护,则NetworkCredentials可能根本不会传递到认证方案中,因为WS-Security不在HTTP级别操作。
您应该做的是通过命令行工具wsdl.exe或类似工具为Web服务创建客户端代理。这将使您可以访问面向Web服务的身份验证方案。
在评论后进行更新:
看起来HttpWebRequest需要接收带有401 UnauthorizedWWW-Authenticate挑战,然后才能在SSL上正确进行身份验证。我猜HttpWebRequests中有两个单独的代码路径处理常规HTTP流量和加密的HTTPS流量。无论如何,您应该尝试的是:
  1. 执行未经身份验证的 HttpWebRequest 请求到 https://.../ URI。
  2. 接收 401 Unauthorized 响应。
  3. 执行相同请求,现在设置了 Credentials(不确定是否应该将 PreAuthenticate 设置为 truefalse;请尝试两者)。
  4. 现在应该会得到你的 Web 服务响应的 200 OK 或其他响应。

另一种选择是在初始请求中自己构建 Authorization 标头:

string credentials = String.Format("{0}:{1}", username, password);
byte[] bytes = Encoding.ASCII.GetBytes(credentials);
string base64 = Convert.ToBase64String(bytes);
string authorization = String.Concat("Basic ", base64);
request.Headers.Add("Authorization", authorization);

抱歉,直到现在我才意识到我正在调用的是REST服务,所以没有wsdl文件。此外,我能够在调试器中跟踪代码,并且可以看到它正确地构建了NetworkCredentials对象,但似乎并没有与HttpWebRequest一起传递。还有一件事 - 我可以通过在浏览器地址栏中输入来成功调用REST服务,因此它必须以这种方式使用我的凭据。 - Russ Clark
1
你还没有写明你使用的身份验证方案以及凭据的来源。此外,如果这是一个REST服务,它不应该有WSDL文件。带有WSDL文件的Web服务通常是SOAP Web服务,这与REST Web服务直接相反。能够使用浏览器访问Web服务(而无需输入任何凭据?)听起来像是受到HTTP身份验证的保护,可能是NTLM。这是真的吗? - Asbjørn Ulsberg
1
你的凭证是否被缓存在浏览器中?你使用的是哪个浏览器?我只熟悉一种身份验证方案,它实际上不会像你所解释的那样向用户发出凭证挑战,那就是NTLM,因为它可以通过将Windows凭证发送到服务器来隐式地进行预身份验证。例如,我相信Internet Explorer会自动执行此操作。 - Asbjørn Ulsberg
我猜这是明文密码。是否可以加密头部? - CharithJ
@CharithJ,如果您不想使用“基本”身份验证方案,则应使用另一种身份验证方案,例如“摘要”(RFC 7616)或“相互”(RFC 8120)。 - Asbjørn Ulsberg
显示剩余5条评论

21

如果你的服务器使用NTLM验证,你可以尝试这个方法:

CredentialCache cc = new CredentialCache();
cc.Add(
    new Uri("https://mywebserver/webpage"), 
    "NTLM", 
    new NetworkCredential("user", "password"));
request.Credentials = cc;

3

尝试将request.PreAuthenticate设置为true。


2
根据这篇文章,它无法正常工作。仍需要一些工作。 - chaZm

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接