【问题标题】:Bearer authentication with System.Net.ICredentials使用 System.Net.ICredentials 进行承载身份验证
【发布时间】:2021-05-10 11:38:29
【问题描述】:

我有一个应用程序可以为给定的 WSDL 地址即时编译服务引用程序集:

  1. 使用 System.Net.WebClient 以 OpenRead 目标服务作为 Stream

  2. 将 WSDL 描述为代码编译单元:https://docs.microsoft.com/en-us/dotnet/api/system.web.services.description.servicedescriptionimporter

    ServiceDescription 描述 = ServiceDescription.Read(stream);

  3. 将单元编译成程序集:https://docs.microsoft.com/en-us/dotnet/api/system.codedom.compiler.codedomprovider.compileassemblyfromdom

然后,该程序集中的所有服务类型都有可以设置的 Credentials(类型 ICredentials),例如

someService.GetType().GetProperty("Credentials").SetValue(someService, new NetworkCredential(userName, password));

基本身份验证场景中按预期工作。

我现在需要开始支持 Bearer authentication(不确定术语是否正确),即在这些服务的请求级别,具有 Authorization 标头,其值为 不记名 是通过 OAuth2 协议获取的 jwt token。身份验证本身起作用,因为我已经在步骤 1 中使用它来读取 WSDL:client.Headers.Add("Authorization", "Bearer ...");

但是,我无法使用 OperationContextScope 将标头 (How to add HTTP Header to SOAP Client) 注入到我的服务引用调用中,因为我编译的类型不包含 InnerChannel

我认为在底层 NetworkCredentials 会产生像 Authorization: Basic 这样的标题。这与我需要的非常相似(Authorization: Bearer ),以至于我无法相信根本没有 ICredentials 子类用于此目的。有没有?我还有其他选择吗?我几乎绝望地编写自己的代理来转发带有该授权标头的所有呼叫。

【问题讨论】:

    标签: c# jwt wsdl credentials


    【解决方案1】:

    我碰巧自己找到了解决办法。

    当使用 ServiceDescriptionImporter 将 WSDL 导入 CodeCompileUnit 时,该单元的所有服务类型都派生自 System.Web.Services.Protocols.SoapHttpClientProtocol。此基类声明可以替换为它的自定义派生,从而覆盖 GetWebRequest 并将自定义 HTTP 标头注入该服务的所有 Web 请求。

    foreach(CodeNamespace ns in unit1.Namespaces)
    {
      foreach(CodeTypeDeclaration t in ns.Types)
      {
        foreach(CodeTypeReference bt in t.BaseTypes)
        {
          if (bt.BaseType == "System.Web.Services.Protocols.SoapHttpClientProtocol")
            bt.BaseType = "MyNamespace.MySoapHttpClientProtocol";
        }
      }
    }
    

    ...

    public class MySoapHttpClientProtocol : System.Web.Services.Protocols.SoapHttpClientProtocol
    {
      protected override WebRequest GetWebRequest(Uri uri)
      {
        var req = base.GetWebRequest(uri);
        req.Headers.Add("Authorization", ...);
        return req; 
      }
    }
    

    要记住的重要一点是,在将服务编译成程序集之前,将包含“MySoapHttpClientProtocol”的当前程序集添加到 CodeDomProvider 引用。

    另外,我加了

    public string AuthToken { get; set; }
    

    MySoapHttpClientProtocol,然后在 GetWebRequest 处作为 Authorization -header 值注入。 AuthToken 可以通过编译类型的反射访问,类似于处理基本身份验证的方式:

    someService.GetType().GetProperty("AuthToken").SetValue(someService, "Bearer ...");
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-17
      • 2017-06-13
      • 2017-03-11
      • 2013-05-30
      • 1970-01-01
      相关资源
      最近更新 更多