SoapCore Asp.net core 3.1 标头

2024-05-06

知道如何使用 SoapCore 为我的调用添加标头吗?

到目前为止我所拥有的:

在startup.cs中:
app.UseSoapEndpoint<IMyService>("/MyService.svc", new BasicHttpBinding(), SoapSerializer.DataContractSerializer);

在 IMyService 中

[ServiceContract]
    public interface IMyService
    {      

        [OperationContract]
        public List<SOADataGetService> GetService(string ServiceType, string ServiceName, string ServiceVersion);
        
    }

然后我的肥皂就变成这样了:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tem="http://tempuri.org/">
   <soapenv:Header/>
   <soapenv:Body>
      <tem:GetService>
         <tem:ServiceType>?</tem:ServiceType>
         <tem:ServiceName>?</tem:ServiceName>
         <tem:ServiceVersion>?</tem:ServiceVersion>
      </tem:GetService>
   </soapenv:Body>
</soapenv:Envelope>

我需要进去<soapenv:Header/>比如用户名和密码


我希望这可以帮助别人。我将 SoapCore 1.1.0.28 与 .Net Core 6 一起使用。我尝试了 @wolfyuk 列出的 Tune 方法,但 Core 总是将字节返回为 null,因此我永远无法通过 null 检查。

我发现最直接的方法是使用 SoapCore 中的 IMessageInspector2 创建中间件来拦截传入的 SOAP 请求并拦截传出的 SOAP 响应。实现 IMessageInspector2 的类可以访问该消息,因此您可以在进入时提取标头(这就是我需要的),并在退出时添加标头。我需要将请求标头包含在我的响应中(我正在通信的系统的要求)。

public class AuthMessageFilter : IMessageInspector2
{
    private const string WsNamespaceSecurityUri = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd";
    private const string WsUserNameTokenNodeName = "UsernameToken";
    private const string WsSecurityNodeName = "Security";
    private const string WsTimestampNodeName = "Timestamp";
    private readonly IMyService _service;
    private readonly IHttpContextAccessor _acc;
    private readonly ILogger _logger;
    private MessageHeaders _messageHeaders;

    public AuthMessageFilter(IHttpContextAccessor acc, IMyService service, ILogger logger)
    {
        _acc = acc;
        _service = service;
        _logger = logger;
    }

    public object AfterReceiveRequest(ref Message message, ServiceDescription serviceDescription)
    {
        ValidateSoapAction();
        var token = GetUserNameToken(message);
        var userIsAuthenticated = _service.ValidateUser(token.Username, token.Password.Value).GetAwaiter().GetResult();
        if (userIsAuthenticated) 
        {
            _messageHeaders = message.Headers; // use in response.
            return null;
        }
        
        const string msg = "The user credentials did not authenticate.";
        _logger.LogEntry(msg);
        throw new AuthenticationFailedException(msg);
    }
    
    private void ValidateSoapAction()
    {
        try
        {
            var soapAction = _acc.HttpContext?.Request.Headers["SOAPAction"].FirstOrDefault()?.Replace("\"", "");
            if (soapAction == null)
            {
                throw new Exception(
                    "Error: Could not extract SoapAction from HttpContext.Request.Headers. Aborting SOAP operation.");
            }
        }
        catch (Exception ex)
        {
            _logger.LogEntry("No SOAP Action found.", ex);
        }
    }

    private WsUsernameToken GetUserNameToken(Message message)
    {
        WsUsernameToken wsUsernameToken = null;
        for (var i = 0; i < _messageHeaders.Count; i++)
        {
            if (!_messageHeaders[i].Name.Equals(WsSecurityNodeName, StringComparison.OrdinalIgnoreCase)) 
                continue;
            
            using var reader = _messageHeaders.GetReaderAtHeader(i);
            while (reader.Read())
            {
                if (reader.IsStartElement() &&
                    reader.NamespaceURI.Equals(WsNamespaceSecurityUri, StringComparison.OrdinalIgnoreCase) &&
                    reader.LocalName.Equals(WsUserNameTokenNodeName, StringComparison.OrdinalIgnoreCase))
                {
                    var serializer = new XmlSerializer(typeof(WsUsernameToken));
                    wsUsernameToken = (WsUsernameToken)serializer.Deserialize(reader);
                    break;
                }
            }
            break;
        }

        if (wsUsernameToken == null)
        {
            var ex = new SecurityException("An exception occurred when verifying security for the message.");
            _logger.LogEntry(LoggingCategory.Service, LoggingLevel.Error, ex.Message, ex);
            throw ex;
        }

        return wsUsernameToken;
    }
    public void BeforeSendReply(ref Message reply, ServiceDescription serviceDescription, object correlationState)
    {
        for (var i = 0; i < _messageHeaders.Count; i++)
        {
            if (!_messageHeaders[i].Name.Equals(WsSecurityNodeName, StringComparison.OrdinalIgnoreCase)) 
                continue;
            
            using var reader = _messageHeaders.GetReaderAtHeader(i);
            while (reader.Read())
            {
                if (reader.IsStartElement() &&
                    reader.NamespaceURI.Equals(WsNamespaceSecurityUri, StringComparison.OrdinalIgnoreCase) &&
                    reader.LocalName.Equals(WsTimestampNodeName, StringComparison.OrdinalIgnoreCase))
                {
                    reply.Headers.Add(_messageHeaders[i] as MessageHeader);
                    break;
                }
            }
            break;
        }
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

SoapCore Asp.net core 3.1 标头 的相关文章

随机推荐