【问题标题】:C# Webservice error: Message security verification failedC# Webservice错误:消息安全验证失败
【发布时间】:2013-08-16 12:12:08
【问题描述】:

我正在尝试使用通过自定义绑定传入带有 UsernameToken 的 SOAP 标头的身份验证 Web 服务

ICollection<BindingElement> bindingElements = new List<BindingElement>();
HttpsTransportBindingElement httpBindingElement = new HttpsTransportBindingElement();
CustomTextMessageBindingElement textBindingElement = new CustomTextMessageBindingElement();
SecurityBindingElement securityElement = SecurityBindingElement.CreateUserNameOverTransportBindingElement();
securityElement.IncludeTimestamp = false;
bindingElements.Add(securityElement);
bindingElements.Add(textBindingElement);
bindingElements.Add(httpBindingElement);
CustomBinding binding = new CustomBinding(bindingElements);

EndpointAddress address = new EndpointAddress("https://....");

var client = new WebServiceClient(binding, address);
client.ClientCredentials.UserName.UserName = "USERNAME HERE";
client.ClientCredentials.UserName.Password = "PASSWORD HERE";

using (new OperationContextScope(client.InnerChannel))
{
    var req = new WebServiceRequest();
    var resp = client.initiate(req);
}

遇到异常:

邮件安全验证失败。

无法从 'BinarySecurityToken' 元素中读取令牌 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd' BinarySecretSecurityToken 的命名空间,带有“oblix:ObSSOCookie” 值类型。如果预计此元素有效,请确保 security 配置为使用具有名称、命名空间和 指定的值类型。"}

服务器堆栈跟踪:

在 System.ServiceModel.Security.TransportSecurityProtocol.VerifyIncomingMessage(Message& 消息,TimeSpan 超时)在 System.ServiceModel.Security.SecurityProtocol.VerifyIncomingMessage(消息& 消息,TimeSpan 超时,SecurityProtocolCorrelationState[] 相关状态)在 System.ServiceModel.Channels.SecurityChannelFactory1.SecurityRequestChannel.ProcessReply(Message reply, SecurityProtocolCorrelationState correlationState, TimeSpan timeout) at System.ServiceModel.Channels.SecurityChannelFactory1.SecurityRequestChannel.Request(消息 消息,TimeSpan 超时)在 System.ServiceModel.Dispatcher.RequestChannelBinder.Request(消息 消息,TimeSpan 超时)在 System.ServiceModel.Channels.ServiceChannel.Call(字符串动作, Boolean oneway, ProxyOperationRuntime 操作, Object[] ins, Object[] 出局,TimeSpan 超时)在 System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall,ProxyOperationRuntime 操作)在 System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage 留言)

fiddler 捕捉到的响应如下:

<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
    <env:Header>
        <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
            <wsse:BinarySecurityToken EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary" ValueType="oblix:ObSSOCookie" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:oblix="http://schemas.oblix.com/ws/2004/04/authentication"><!--REMOVED--></wsse:BinarySecurityToken>
        </wsse:Security>
    </env:Header>
    <env:Body>
        <MobileAppsLoginSSOProcessResponse  xmlns="http://xmlns.oracle.com/MobileAppsLoginSSO">
            <ReturnStatus>SUCCESS</ReturnStatus>
        </MobileAppsLoginSSOProcessResponse>
    </env:Body>
</env:Envelope>

我正在使用 http://msdn.microsoft.com/en-us/library/ms751486%28v=vs.100%29.aspx 之后的 CustomTextMessageEncoder

编辑:

正如 Yaron 所建议的,除非我从响应中去除 BinarySecurityToken 标记,否则代码将失败并出现上述消息安全验证失败异常。

响应中的“oblix:ObSSOCookie”是服务在成功身份验证后发送回客户端的身份验证 cookie,我相信客户端需要保存此 cookie。

解决方案: 正如 Yaron 在最终编辑中所建议的,我从自定义绑定中删除了 SecurityElementBinding,并使用自定义消息检查器 (IClientMessageInspector) 将安全标签注入到标头中。

这仅允许解释来自 SOAP 主体的响应,并且我可以在我的 IClientMessageInspector 实现的 AfterReceiveReply 中读取 SOAP 响应标头。

【问题讨论】:

    标签: wcf c#-4.0


    【解决方案1】:

    服务器在响应中返回一个 x.509 令牌,而 WCF 不确定如何处理它(用户名身份验证中不需要此令牌)。我看到两个选项:

    1. 在您的编码器中从响应中删除安全标签

    2. 根本不使用安全性,并且在编码器(或消息检查器,如果您愿意)将用户/传递标头推送到请求

    编辑:您说客户端应在进一步调用中使用此令牌。我不确定处理这个问题的正确方法是什么,所以我会给出一个可行的快速方法(但感觉有点不完整)。根本不定义任何安全性(从绑定中删除安全元素)。然后使用自定义消息检查器(或编码器,但更难)以正确的格式推送用户/传递的消息(查看使用安全绑定时它们是如何发送的)。这应该不难。那么 WCF 将不会在响应时验证令牌。您可以使用已有的消息检查器来检查响应并提取令牌。您的主类(初始化代理)也是初始化检查器的类,因此它应该有权访问其数据成员以访问令牌并重新发送它。

    如果服务器将令牌发送到正文而不是标题中,那就容易多了。 也可能有一种方法可以通过实现自定义标记/行为以非修补方式做到这一点,但在我看来,这增加了更多抽象,最好是具体的。

    【讨论】:

    • 响应在 Security > BinarySecurityToken 中包含身份验证令牌。我不确定它没有用。
    • 您能否建议一些方法来处理安全标签,而不会出现此异常?
    • 好的,现在我看到这不是常规的 x.509 令牌,而是称为 oblix:ObSSOCookie 的东西。此 cookie 是 WCF 无法立即处理的。您或供应商都知道如何操作,在这种情况下您应该实现 WCF 自定义令牌,或者您决定不关心它并按照上面的建议将其删除。您需要与供应商讨论此 cookie 的含义以及您应该如何处理/验证它。继承人如何创建自定义令牌这是正确的方法,
    • 我假设你也可以做一些更快速和肮脏的事情,比如在方法代码msdn.microsoft.com/en-us/library/ms731872.aspx 中进行验证
    • 不确定我是否理解您关于使用自定义令牌的建议。我能够将带有 UsernameToken 的 Security 标头发送到服务,然后服务正确地验证用户名。唯一的问题是服务发送回客户端的 BinarySecurityToken 会导致问题。您是否建议使用自定义令牌而不是客户端发送给服务的 UsernameToken?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-20
    • 2019-04-08
    • 2019-12-12
    • 2015-12-14
    • 1970-01-01
    相关资源
    最近更新 更多