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