调用Web服务时C#报HTTP 401未授权,Postman可正常请求
问题:C#调用带Bearer认证的SOAP服务返回401,仅Postman可正常请求
我在C#控制台应用里通过添加服务引用调用一个需要Bearer认证的Web服务,Postman发起请求能正常拿到响应,但C#代码调用返回HTTP 401错误,甚至SOAPUI调用也报同样的401。
Postman对应的CURL命令
curl --location 'https://api-secure-uat.com/v1' \ --header 'Content-Type: text/xml' \ --header 'SOAPAction: http://secure.com/Services/v1/CreateSession' \ --header 'Authorization: Bearer qv5bBU9HuQ0F5p3CT5EXAXbXd3w2' \ --data '<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <soap:Body> <CreateSession xmlns="http://secure.com/Services/v1/"> <reqCreateSession> <client> <name>hrix03hQoSwweIE1NuHrDHu5Ooz66jmx</name> <clientId>hrix03hQoSwweIE1NuHrDHu5Ooz66jmx</clientId> <appservername>test-client</appservername> <appserverip>10.10.10.10</appserverip> <appservertimestamp>2023-12-26T16:28:59.704Z</appservertimestamp> <SubClientId xsi:nil="true"/> <SubClientName xsi:nil="true"/> <SalesAgentId xsi:nil="true"/> <SalesAgentName xsi:nil="true"/> </client> </CreateSession> </soap:Body> </soap:Envelope>'
我使用的C#调用代码
BasicHttpBinding binding = new BasicHttpBinding { Security = new BasicHttpSecurity { Mode = BasicHttpSecurityMode.Transport } }; // Create an instance of the service client CoAServicesClient optixServiceclient = new CoAServicesClient(binding, new EndpointAddress(url)); // Add Bearer token to the HTTP request headers HttpRequestMessageProperty requestProperty = new HttpRequestMessageProperty(); requestProperty.Headers["Authorization"] = $"Bearer {bearerToken}"; OperationContextScope contextScope = new OperationContextScope(optixServiceclient.InnerChannel); OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = requestProperty; try { // Calling service method here CreateSessionResponse csResponse = optixServiceclient.CreateSessionAsync(GetCreateSessionObject()).Result; // Process the result here Console.WriteLine($"Service response: {csResponse}"); } catch (Exception ex) { Console.WriteLine($"Error calling service: {ex.Message}"); }
排查方向及解决方案
1. 缺失SOAPAction请求头
Postman的请求里明确带了SOAPAction头,但你的C#代码没有设置这个头。很多SOAP服务会严格校验这个头,缺失就会返回401或400。
修改代码,在HttpRequestMessageProperty里添加SOAPAction头:
requestProperty.Headers["SOAPAction"] = "http://secure.com/Services/v1/CreateSession";
2. 同步调用导致上下文丢失
你用了.Result同步等待异步方法,可能会导致OperationContextScope的上下文在请求发送前就被释放,Authorization头没被正确附加。改成异步await方式:
// 把方法改成async Task async Task CallService() { BasicHttpBinding binding = new BasicHttpBinding { Security = new BasicHttpSecurity { Mode = BasicHttpSecurityMode.Transport } }; using (CoAServicesClient optixServiceclient = new CoAServicesClient(binding, new EndpointAddress(url))) using (new OperationContextScope(optixServiceclient.InnerChannel)) { HttpRequestMessageProperty requestProperty = new HttpRequestMessageProperty(); requestProperty.Headers["Authorization"] = $"Bearer {bearerToken}"; requestProperty.Headers["SOAPAction"] = "http://secure.com/Services/v1/CreateSession"; OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = requestProperty; try { CreateSessionResponse csResponse = await optixServiceclient.CreateSessionAsync(GetCreateSessionObject()); Console.WriteLine($"Service response: {csResponse}"); } catch (Exception ex) { Console.WriteLine($"Error calling service: {ex.Message}"); } } }
3. 抓包对比请求差异
用Fiddler或Charles抓Postman和C#的请求,对比以下内容:
- 所有请求头的名称、值是否完全一致(注意大小写,部分服务对Header大小写敏感)
- 请求体的XML结构、命名空间是否和Postman一致
- 确认Authorization头是否确实出现在C#发送的请求里
4. 检查SOAPUI的配置
SOAPUI报同样错误,说明不是C#代码独有的问题,大概率也是缺失SOAPAction头或者头格式不对。在SOAPUI的请求配置里手动添加SOAPAction和Authorization头,再测试。
内容的提问来源于stack exchange,提问作者Coca Coffee
相关产品推荐
相关产品推荐

