Как пройти аутентификацию в Workday API в ядре .NET?

Я пытаюсь подключиться к Workday API (SOAP) из функций Azure в.NET Core, но у меня возникают проблемы с аутентификацией.

Из того, что я видел, проблема связана с использованием аутентификации по транспорту, поэтому я попытался использовать пользовательские привязки, но похоже, что.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 не поддерживается.

2 ответа

Решение

Функция сообщений в системе безопасности пока не поддерживается в asp.net core-2.0.

Вы можете проверить полный список поддерживаемых функций здесь: https://github.com/dotnet/wcf/blob/master/release-notes/SupportedFeatures-v2.0.0.md

В качестве альтернативы вы можете попытаться создать свой собственный SOAP-конверт, подобный сборке веб-API на.Net Standard, который будет выполнять меры безопасности за вас, и вы можете просто вызвать его из своей функции Azure с помощью httpclient. Я не пробовал, но я получил эту идею из сообщения ниже:

Как вызвать службу XML SOAP, которая требует подписи из.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 специально для моего случая.

Другие вопросы по тегам