gpt4 book ai didi

c# - 用于从 .NET Core 应用程序调用 WCF 服务发送 cookie 的中间件

转载 作者:行者123 更新时间:2023-12-04 09:25:55 34 4
gpt4 key购买 nike

我目前正在开发一个客户端以连接到一个 API,该 API 是几个 SOAP 服务端点的外观。我正在使用.Net Core 3.1
SOAP 服务是由其他公司编写的,无法更改。我们有多个服务,每个服务都有“登录”方法。成功登录后, session cookie 在 header 中返回。 Cookie 需要附加到每个后续调用以访问其他方法。
为此,我们编写了中间件,假设 捕获登录方法的响应,并存储 cookie。然后它应该改变对 WCF 服务的请求,将 cookie 添加到 header 中。
不幸的是,只有在调用我们的 API 路径时才会触发中间件,而不是在进行 SOAP 服务调用时。假设我在我的 API 中调用路径“/test”。 middeware 被正确提升并执行。之后,我的代码在执行 SOAP 服务调用时执行,不幸的是中间件没有被触发。
我研究了许多主题,例如 THISTHIS
但我们希望能够在每次调用时全局更改消息,而不是“手动”显式添加 cookie。此外,当 session 过期时,我们希望捕捉到这种情况并再次登录,而不会引起用户注意。这就是为什么编写中间件类如此重要的原因。
所以我有我的连接服务(使用 Microsoft WCS Web 服务引用提供程序生成的代理),调用如下:

MyServiceClient client = new MyServiceClient();

var logged = await client.loginAsync(new loginRequest("login", "password"));

if (logged.@return) {

//doing stuff here (getting cookie, storing in places)

}
登录异步 方法响应的 header 中有 cookie。我们如何注册某种中间件或拦截器来获取响应并从此方法中提取 cookie?
比,我们有服务电话:
 var data = await client.getSchedule(new getScheduleRequest(DateTime.Parse("2020-06-01"), DateTime.Parse("2020-06-23")));
现在我希望我的消息检查器/中间件/拦截器更改请求并将存储的 cookie 添加为 header 。
中间件在 Startup.cs 中注册:
app.UseMiddleware<WCFSessionMiddleware>();
我也尝试过使用行为,但问题是一样的 - 每次我创建 wcf 服务客户端时都需要调用它来改变行为,使用:
client.Endpoint.EndpointBehaviors.Add(myBehaviour);
无论多小,我都会给予任何帮助。

最佳答案

这取决于您使用的 Binding,但默认情况下,客户端应自动发送在其先前发出的请求中收到的 cookie。
例如:

var client = new ServiceClient(...);
var result = await client.MethodAsync(param); // If the response contains a HTTP Header 'Set-Cookie: cookieName=cookieValue'
var anotherResult = await client.AnotherMethodAsync(anotherParam); // Then this request will contain a HTTP Header 'Cookie: cookieName=cookieValue'
这是因为自动生成的绑定(bind)代码类似于:
private static System.ServiceModel.Channels.Binding GetBindingForEndpoint(EndpointConfiguration endpointConfiguration)
{
if ((endpointConfiguration == EndpointConfiguration.BasicHttpBinding_IService))
{
System.ServiceModel.BasicHttpBinding result = new System.ServiceModel.BasicHttpBinding();
result.MaxBufferSize = int.MaxValue;
result.ReaderQuotas = System.Xml.XmlDictionaryReaderQuotas.Max;
result.MaxReceivedMessageSize = int.MaxValue;
result.AllowCookies = true; // <- THIS
return result;
}
throw new System.InvalidOperationException(string.Format("Could not find endpoint with name \'{0}\'.", endpointConfiguration));
}
如果您需要手动读取/设置 cookie,您可以使用 IEndpointBehavior,但请注意,这与中间件管道无关。中间件管道是处理传入 ASP.NET 应用程序的请求,我们将讨论的行为是处理从应用程序到 WCF 服务的请求。
public class MyEndpointBehavior : IEndpointBehavior
{
private MyMessageInspector messageInspector = new MyMessageInspector();
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
}

public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
clientRuntime.ClientMessageInspectors.Add(messageInspector);
}

public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
}

public void Validate(ServiceEndpoint endpoint)
{
}
}
这是消息检查器:
// Reads a cookie named RESP_COOKIE from responses and put its value in a cookie named REQ_COOKIE in the requests
public class MyMessageInspector : IClientMessageInspector
{
private const string RESP_COOKIE_NAME = "RESP_COOKIE";
private const string REQ_COOKIE_NAME = "REQ_COOKIE";
private string cookieVal = null;

// Handles the service's responses
public void AfterReceiveReply(ref Message reply, object correlationState)
{
HttpResponseMessageProperty httpReplyMessage;
object httpReplyMessageObject;
// WCF can perform operations with many protocols, not only HTTP, so we need to make sure that we are using HTTP
if (reply.Properties.TryGetValue(HttpResponseMessageProperty.Name, out httpReplyMessageObject))
{
httpReplyMessage = httpReplyMessageObject as HttpResponseMessageProperty;
if (!string.IsNullOrEmpty(httpReplyMessage.Headers["Set-Cookie"]))
{
var cookies = httpReplyMessage.Headers["Set-Cookie"];
cookieVal = cookies.Split(";")
.Select(c => c.Split("="))
.Select(s => new { Name = s[0], Value = s[1] })
.FirstOrDefault(c => c.Name.Equals(RESP_COOKIE_NAME, StringComparison.InvariantCulture))
?.Value;
}
}
}

// Invoked when a request is made
public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
HttpRequestMessageProperty httpRequestMessage;
object httpRequestMessageObject;
if (!string.IsNullOrEmpty(cookieVal))
{
var prop = new HttpRequestMessageProperty();
prop.Headers.Add(HttpRequestHeader.Cookie, $"{REQ_COOKIE_NAME}={cookieVal}");
request.Properties.Add(HttpRequestMessageProperty.Name, prop);
}
return null;
}
}
然后我们可以像这样配置它:
var client = new ServiceClient(...);
client.Endpoint.EndpointBehaviors.Add(new MyEndpointBehavior());

关于c# - 用于从 .NET Core 应用程序调用 WCF 服务发送 cookie 的中间件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63009279/

34 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com