2

我需要使用用户名令牌来验证 Primavera P6 Web 服务。我在 VS2010 中创建了控制台应用程序并添加了一个服务引用:

http://localhost:8206/p6ws/services/ExportService?wsdl

所以此刻我有一个代理类,我可以写这样的东西:

var exportService = new ExportPortTypeClient();
var project = new ExportProject { ProjectObjectId = 1000 };
exportService.ExportProject(project);

当我尝试调用 ExportProject() 时,由于身份验证失败而出现异常。

有没有人有使用用户名令牌进行身份验证的示例代码?

4

2 回答 2

4

确保使用这样的自定义绑定创建客户端:

var securityElement = SecurityBindingElement.CreateUserNameOverTransportBindingElement();                
securityElement.AllowInsecureTransport = true; //in case you don't use SSL
securityElement.EnableUnsecuredResponse = true; //in case you don't use SSL
var encodingElement = new TextMessageEncodingBindingElement(MessageVersion.Soap11, Encoding.UTF8);
var transportElement = new HttpTransportBindingElement();
var binding = new CustomBinding(securityElement, encodingElement, transportElement);

EndpointAddress endpointAddress = new EndpointAddress("<your endpoint to service goes here>");

var exportService = new ExportPortTypeClient(binding, endpointAddress);
var project = new ExportProject { ProjectObjectId = 1000 };
exportService.ExportProject(project);
于 2014-01-15T11:11:40.973 回答
2

我终于找到了一个在 P6 WebServices 中使用用户名令牌的解决方案。它并不像你想象的那么简单。您需要包含 WSE 标头。

解决方案在Rick Strahl 的博客上。

public class CustomTokenSerializer : WSSecurityTokenSerializer {
    public CustomTokenSerializer(SecurityVersion sv)
        : base(sv) { }

    protected override void WriteTokenCore(XmlWriter writer, SecurityToken token) {
        var userToken = token as UserNameSecurityToken;
        var tokennamespace = "o";
        var nonce = GetSHA1String(Guid.NewGuid().ToString());
        writer.WriteRaw(
                $@"<{tokennamespace}:UsernameToken u:Id=""{token.Id}"" xmlns:u=""http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\"">
                <{tokennamespace}:Username>{userToken.UserName}</{tokennamespace}:Username>
                <{tokennamespace}:Password Type=""http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText\"">{userToken.Password}</{tokennamespace}:Password>
                <{tokennamespace}:Nonce EncodingType=""http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary\"">{nonce}</{tokennamespace}:Nonce>
            </{tokennamespace}:UsernameToken>"
            );
    }

    protected string GetSHA1String(string phrase) {
        SHA1CryptoServiceProvider sha1Hasher = new SHA1CryptoServiceProvider();
        byte[] hashedDataBytes = sha1Hasher.ComputeHash(Encoding.UTF8.GetBytes(phrase));
        return Convert.ToBase64String(hashedDataBytes);
    }

}

我正在使用 ChannelFactory 来创建客户端。

public class WebServiceClientFactory<T> : IWebServiceClientFactory<T> {

    public WebServiceClientFactory() {
        ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
        ServicePointManager.Expect100Continue = true;
        ServicePointManager.DefaultConnectionLimit = 9999;
    }

    public T GetClient(Credentials cred) {

        ChannelFactory<T> channelFactory = new ChannelFactory<T>(GetBinding(), new EndpointAddress(cred.Url));
        channelFactory.Endpoint.Behaviors.Remove<System.ServiceModel.Description.ClientCredentials>();
        channelFactory.Endpoint.Behaviors.Add(new CustomCredentials());
        channelFactory.Endpoint.Behaviors.Add(new CustomP6DbInstanceBehavior(cred.DatabaseInstanceId));

        channelFactory.Credentials.UserName.UserName = cred.Username;
        channelFactory.Credentials.UserName.Password = cred.Password;

        return channelFactory.CreateChannel();
    }

    private Binding GetBinding() {
        var security = SecurityBindingElement.CreateUserNameOverTransportBindingElement();
        security.IncludeTimestamp = false;
        var encoding = new TextMessageEncodingBindingElement(MessageVersion.Soap11, Encoding.UTF8);
        var transport = new HttpsTransportBindingElement {
            MaxReceivedMessageSize = 20000000 // 20 megs
        };
        return new CustomBinding(security, encoding, transport);
    }

}
于 2018-01-17T18:30:12.107 回答