如何在 .net 核心中对 Workday API 进行身份验证?

How to authenticate to Workday API in .net core?

我正在尝试从 .NET Core 中的 Azure Functions 连接到 Workday API (SOAP),但我遇到了一些身份验证问题。

据我所知,问题出在通过传输使用身份验证,因此我尝试使用自定义绑定,但看起来 .NET Core 尚不支持它。

SecurityBindingElement sb = SecurityBindingElement.CreateUserNameOverTransportBindingElement();

sb.IncludeTimestamp = false;

const int lim = Int32.MaxValue;
var timeout = TimeSpan.FromMinutes(2);

var cb = new CustomBinding(
    sb,
    new TextMessageEncodingBindingElement(MessageVersion.Soap11, Encoding.UTF8)
    {
        ReaderQuotas = new XmlDictionaryReaderQuotas
        {
            MaxDepth = lim,
            MaxStringContentLength = lim,
            MaxArrayLength = lim,
            MaxBytesPerRead = lim,
            MaxNameTableCharCount = lim
        }
    },
    new HttpsTransportBindingElement
    {
        MaxReceivedMessageSize = lim,
        MaxBufferSize = lim,

    })
{
    SendTimeout = timeout,
    ReceiveTimeout = timeout
};

var client = new WorkDayAbsenceServiceReference.Absence_ManagementPortClient(cb, new EndpointAddress("https://wd3-impl-services1.workday.com/ccx/service/mytenant/Absence_Management/v33.0"));
client.ClientCredentials.UserName.UserName = "myusername";
client.ClientCredentials.UserName.Password = "mypassword";

var headers = new WorkDayAbsenceServiceReference.Workday_Common_HeaderType() {};

var requestType = new WorkDayAbsenceServiceReference.Get_Time_Off_Plan_Balances_RequestType()
{
    Request_Criteria = new WorkDayAbsenceServiceReference.Time_Off_Plan_Balance_Request_CriteriaType()
    {
        Employee_Reference = new WorkDayAbsenceServiceReference.WorkerObjectType()
        {
            ID = new WorkDayAbsenceServiceReference.WorkerObjectIDType[]
            {
                new WorkDayAbsenceServiceReference.WorkerObjectIDType
                {
                    type = "Employee_ID",
                    Value = "_0000028"
                }
            }
        }
    }
};


var test = await client.Get_Time_Off_Plan_BalancesAsync(headers, requestType);

我得到的错误代码:

System.Private.CoreLib: 执行函数时出现异常:GetDaysOff。 System.Private.ServiceModel: 不支持TransportSecurityBindingElement.BuildChannelFactoryCore。

asp.net core-2.0 尚不支持安全消息功能。

您可以在此处查看支持功能的完整列表:https://github.com/dotnet/wcf/blob/master/release-notes/SupportedFeatures-v2.0.0.md

或者,您可以尝试创建自己的 SOAP 信封类型的 Web api 构建在 .Net Standard 上,它将为您提供安全保护,您可以使用 httpclient 从 Azure 函数中简单地调用它。我没试过,但我从下面得到了这个想法 post:

How Do I Call XML SOAP Service that Requires Signature from .Net Core?

private static HttpClient Client = new HttpClient(); 

Uri uri = new Uri("https://thirdparty.com/service.svc");
X509Certificate2 cert = // from some store etc
var envelope = BuildEnvelope(cert);

using (HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, uri))
{
    request.Content = new StringContent(envelope, Encoding.UTF8, "application/soap+xml");
    using (HttpResponseMessage response = Client.SendAsync(request).Result)
    {
        if (response.IsSuccessStatusCode)
        {
            response.Content.ReadAsStringAsync().ContinueWith(task =>
            {
                string thirdparty_envelope = task.Result;
                XElement thirdparty_root = XElement.Parse(thirdparty_envelope);
                // etc
            }, TaskContinuationOptions.ExecuteSynchronously);
        }
    }
}

附加参考:

https://github.com/dotnet/wcf/issues/13

https://github.com/dotnet/wcf/issues/8

或者,您可以将 Microsoft Logic 应用程序与 Workday 连接器结合使用,然后您可以使用端点。虽然它处于预览阶段,但您也可以实现自定义连接器。

https://docs.microsoft.com/en-us/connectors/custom-connectors/create-register-logic-apps-soap-connector

希望对您有所帮助,请随时在您的对话中标记我。

非常感谢 Mohit Verma,在花了几个小时构建 SOAP Envelope 之后,我能够从 Workday API.

获取日期

我的代码使用 WSS 密码文本安全性进行身份验证:

string uriBase = Environment.GetEnvironmentVariable("UriBaseWorkdayAbsenceManagement");
        string user = Environment.GetEnvironmentVariable("WorkdayUsername");
        string pass = Environment.GetEnvironmentVariable("WorkdayPassword");

        string xml;
        XmlWriterSettings settings = new XmlWriterSettings();
        settings.OmitXmlDeclaration = true;
        using (MemoryStream ms = new MemoryStream())
        {
            using (XmlWriter writer = XmlWriter.Create(ms, settings))
            {
                XmlSerializerNamespaces names = new XmlSerializerNamespaces();
                names.Add("soapenv", "http://schemas.xmlsoap.org/soap/envelope/");
                names.Add("bsvc", "urn:com.workday/bsvc");
                XmlSerializer cs = new XmlSerializer(typeof(Envelope));
                var myEnv = new Envelope()
                {
                    Header = new EnvelopeHeader()
                    {
                        Security = new Security()
                        {
                            UsernameToken = new SecurityUsernameToken()
                            {
                                Username = user,
                                Password = new SecurityUsernameTokenPassword()
                                {
                                    Type = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText",//update type to match your case
                                    Value = pass
                                }
                            }
                        }
                    },
                    Body = new EnvelopeBody()
                    {
                        get_Time_Off_Plan_Balances_RequestType = new WorkDayAbsenceServiceReference.Get_Time_Off_Plan_Balances_RequestType()
                        {
                            Request_Criteria = new WorkDayAbsenceServiceReference.Time_Off_Plan_Balance_Request_CriteriaType()
                            {
                                Employee_Reference = new WorkDayAbsenceServiceReference.WorkerObjectType()
                                {
                                    ID = new WorkDayAbsenceServiceReference.WorkerObjectIDType[]
                                    {
                                        new WorkDayAbsenceServiceReference.WorkerObjectIDType
                                        {
                                            type = "Employee_ID",
                                            Value = workerId
                                        }
                                    }
                                }
                            }
                        }
                    }
                };


                cs.Serialize(writer, myEnv, names);
                ms.Flush();
                ms.Seek(0, SeekOrigin.Begin);
                StreamReader sr = new StreamReader(ms);
                xml = sr.ReadToEnd();
            }
        }

        SoapEnvelope responseEnvelope = null;
        using (var client = SoapClient.Prepare().WithHandler(new DelegatingSoapHandler()
        {
            OnHttpRequestAsyncAction = async (z, x, y) =>
            {
                x.Request.Content = new StringContent(xml, Encoding.UTF8, "text/xml");
            }
        }))
        {
            responseEnvelope = client.SendAsync(uriBase, "action", SoapEnvelope.Prepare()).Result;
        }

Body Envelope 特定于我的情况。