WCF通用合约和UsernameToken

时间:2015-06-24 13:25:02

标签: c# wcf security soap

我有一个使用WSHttpBinding的自托管soap服务器。除了一些操作,它还提供了一个通用的合同接口:

[ServiceContract(Namespace = "http://myns")]
public interface IGenericService
{
    [OperationContract]
    string GetData(int value);

    [OperationContract(Action = "*", ReplyAction = "*")]
    Message ProcessMessage(Message message);
}

主持人应使用自己的UserNamePasswordValidator。我这样设置:

ServiceCredentials servCredBehav = new ServiceCredentials();
servCredBehav.UserNameAuthentication.UserNamePasswordValidationMode   = UserNamePasswordValidationMode.Custom;
servCredBehav.UserNameAuthentication.CustomUserNamePasswordValidator  = new MyUserNamePasswordValidator();
host.Description.Behaviors.Add(servCredBehav);

WSHttpBinding binding = new WSHttpBinding(SecurityMode.TransportWithMessageCredential);
binding.Name = "WS_SOAP_12";
...
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
binding.Security.Message.ClientCredentialType = MessageCredentialType.UserName;

这是(已清理过的)验证器:

public class MyUserNamePasswordValidator : UserNamePasswordValidator
{
    public override void Validate(string userName, string password)
    {
        if (userName != "test" && password != "test123")
            throw new SecurityTokenException("Invalid user name or incorrect password");
    } 
}

当我使用visual studio创建代理并调用GetData时,这很好用:

using (GenericService12Https.GenericServiceClient bla = new GenericService12Https.GenericServiceClient())
{
    bla.ClientCredentials.UserName.UserName = "test";
    bla.ClientCredentials.UserName.Password = "test123";

    bla.Open();
    string s = bla.GetData(5);
}

当我使用HttpWebRequest等低级方法访问此soap服务并直接向其发送xml以便调用ProcessMessage()时,会出现问题。

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
    <soap:Header xmlns:wsa="http://www.w3.org/2005/08/addressing" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
        <wsse:Security soap:mustUnderstand="1" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
            <wsse:UsernameToken wsu:Id="uuid-412594ae-2641-4b2f-8458-631e17940108-1">
                <wsse:Username>test</wsse:Username>
                <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">test123</wsse:Password>
            </wsse:UsernameToken>
        </wsse:Security>
        <wsa:MessageID>...</wsa:MessageID>
        <wsa:To>https://localhost:44301/Receiver.svc</wsa:To>
        <wsa:Action>...</wsa:Action>
    </soap:Header>
    <soap:Body>
        <Dummy/>
    </soap:Body>
</soap:Envelope>

服务器返回包含该内容的HTTP 500错误(原始错误,德语,通过谷歌翻译):

  

无法处理邮件。可能的原因:行动&#34; ...   &#34;如果错误,则邮件包含无效或过期的安全性   上下文令牌或债券之间是冲突。安全上下文   如果服务具有该通道,则令牌将无效   由于不活动而终止。增加的接收超时   绑定服务端点以防止服务终止空闲   会议过早。

要么我用

binding.Security.Message.ClientCredentialType = MessageCredentialType.None;

然后我可以在ProcessMessage()中手动检查凭据,但可以未经授权访问GetData()或

binding.Security.Message.ClientCredentialType = MessageCredentialType.UserName;

这样GetData()按预期工作,但从不调用ProcessMessage()。

有关如何为所有操作和通用合同启用用户名/密码验证的任何建议? 顺便说一句。我不能改变xml标题,因为它们来自外国系统。

0 个答案:

没有答案