[英]How to authenticate to Workday API in .net core?
I'm trying to connect to Workday API (SOAP) from Azure Functions in .NET Core, but I'm encountering some issues with authentication.我正在尝试从 .NET Core 中的 Azure 函数连接到 Workday API (SOAP),但我遇到了一些身份验证问题。
From what I've seen, the problem comes from using authentication over transport, so I tried to use custom bindings but looks like .NET Core doesn't support it yet.据我所见,问题来自使用传输身份验证,所以我尝试使用自定义绑定,但看起来 .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);
And the error code I get:我得到的错误代码:
System.Private.CoreLib: Exception while executing function: GetDaysOff. System.Private.CoreLib:执行 function 时出现异常:GetDaysOff。 System.Private.ServiceModel: TransportSecurityBindingElement.BuildChannelFactoryCore is not supported. System.Private.ServiceModel:不支持 TransportSecurityBindingElement.BuildChannelFactoryCore。
Thank you very much Mohit Verma , after spending few hours to build the SOAP Envelope, I was be able to get date from the Workday API.非常感谢Mohit Verma ,在花了几个小时构建 SOAP 信封后,我能够从 Workday API 获取日期。
There is my code using WSS Password Text security for authentication:我的代码使用 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 is specific to my case.身体信封特定于我的情况。
Message feature in security is not yet supported in asp.net core-2.0. asp.net core-2.0 尚不支持安全中的消息功能。
You can check a full list of supported feature here: https://github.com/dotnet/wcf/blob/master/release-notes/SupportedFeatures-v2.0.0.md您可以在此处查看受支持功能的完整列表: https://github.com/dotnet/wcf/blob/master/release-notes/SupportedFeatures-v2.0.0.md
Alternatively you can try to create your own SOAP envelope kind of a Web api build on.Net Standard which will do security stuff for you and you can simple call it from your Azure function using httpclient. Alternatively you can try to create your own SOAP envelope kind of a Web api build on.Net Standard which will do security stuff for you and you can simple call it from your Azure function using httpclient. I haven't tried it but i got this idea from below post:我没有尝试过,但我从下面的帖子中得到了这个想法:
How Do I Call XML SOAP Service that Requires Signature from.Net Core? 如何调用需要.Net Core签名的XML SOAP服务?
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);
}
}
}
Additional reference:附加参考:
https://github.com/dotnet/wcf/issues/13 https://github.com/dotnet/wcf/issues/13
https://github.com/dotnet/wcf/issues/8 https://github.com/dotnet/wcf/issues/8
Alternatively, you can use Microsoft Logic app with Workday connector and then you can use the endpoint.或者,您可以将 Microsoft Logic 应用程序与 Workday 连接器一起使用,然后您可以使用端点。 Though it's in preview, but you can implement your custom connector as well.虽然它处于预览阶段,但您也可以实现自定义连接器。
https://docs.microsoft.com/en-us/connectors/custom-connectors/create-register-logic-apps-soap-connector https://docs.microsoft.com/en-us/connectors/custom-connectors/create-register-logic-apps-soap-connector
Hope it helps, Feel free to tag me in your conversation.希望对您有所帮助,请随时在您的对话中标记我。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.