【问题标题】:Get client application name to web service将客户端应用程序名称获取到 Web 服务
【发布时间】:2014-02-20 17:40:32
【问题描述】:

我正在更新一个用 C# 用 VS2012 编写的 Web 服务应用程序,我想在其中获取客户端应用程序名称。

我可以进行系统调用来获取此值吗?

原来,在 web 服务应用程序中有以下代码行:

string ApplicationID = 
       System.ServiceModel.ServiceSecurityContext.Current.PrimaryIdentity.Name;

这个 .Name 值返回用户名,我需要客户端应用程序名称。

我怎样才能安全地获取客户端的应用程序名称?

  • 更新: 似乎 ClientCredential 类可用于设置用户名,例如:

    service1.ClientCredentials.UserName.UserName = "ClientTestApp";

在客户端应用程序中,您可以使用以下方式访问 Web 服务应用程序中的用户名:

 string TestAppName = System.ServiceModel.ServiceSecurityContext.Current.PrimaryIdentity.Name;

应该如何配置端点的绑定?

更新:

在下面的评论中举例说明我的意思......

客户申请:

        Service1.ClientCredentials.UserName.UserName = "ClientAppName";

        try
        {
            Service1.Method1(ProfileID, OrderID);
        }
        catch (Exception ex)
        {
            string Error = ex.Message;
        }

网络服务方式:

 public void Method1(long ProfileID, int OrderID)
    {
        //The ApplicationID will be "ClientAppName"
        string ApplicationID = ServiceSecurityContext.Current.PrimaryIdentity.Name;
        try
        {
            //CHeck the ApplicationID and do stuff...
        }
    }

配置文件 绑定可能必须包含 UserName 的凭据。但我似乎无法获得正确的配置以使其正常工作。

我所描述的可能吗?

更新

我已经阅读了很多关于使用这些安全元素和属性设置配置文件的内容。但我还在学习。因此,对于提出一些基本问题,我提前道歉。

我在 Web 服务应用程序中为 ApplicationID 分配了一个值:

string ApplicationID = ServiceSecurityContext.Current.PrimaryIdentity.Name;

通过使用此绑定配置:

<wsHttpBinding>
      <binding name="ServiceEndpoint"  closeTimeout="00:01:00">
        <security mode="Message">
        </security> 
      </binding>
</wsHttpBinding>

然而,值存储在

ServiceSecurityContext.Current.PrimaryIdentity.Name;

是我在 SQL Server 2012 Management Studio 中用于 Windows 身份验证的用户名。

根据文档,ServiceSecurityContext 类应返回以下内容: “表示远程方的安全上下文。在客户端上,代表服务身份,在服务上,代表客户端身份。”

如何获得这个用户名值?

无论如何我可以用另一个值设置它吗?

通过使用 wsHttpBinding 和 Message 属性,这是否意味着它使用了 SOAP 消息安全性? (正文已加密和签名。)

尝试其他方法 如果我设置 ClientCredentials.UserName.UserName = "TestClient" ClientCredentials.UserName.Password = "一些密码" 在客户端测试应用程序中。

添加 UserNamePasswordValidator 类并覆盖 Validate() 方法。在此方法中,它会检查数据库中的表中的用户名和密码。

我当前使用 wsHttpBinding 的配置文件是这样的:

<wsHttpBinding>
  <binding name="PaymentSecureServiceEndpoint"  closeTimeout="00:01:00">
    <security mode="Message">
      <message clientCredentialType="UserName"/>
    </security> 
  </binding>
</wsHttpBinding>

当我尝试更新服务引用时,我收到错误消息: '未提供服务证书。在 ServerCredentials 中指定服务证书。'

有没有什么方法可以在不提供服务证书的情况下使用 validate() 方法? ServerCredentials 是否必须在服务级别,可以在端点级别吗? 这会将 PrimaryIdentity.Name 值设置为我在客户端应用程序中设置的 UserName 吗?

谢谢...一如既往。

添加自签名证书

我的自签名证书的名称是:TestCert。 我放证书的位置是: 控制台根目录/证书(本地计算机)/个人/证书。

这是在 web.config 文件中定义的服务行为:

 <behavior name="SecureBehavior">
      <serviceCredentials>
        <userNameAuthentication userNamePasswordValidationMode="Custom" 
                                customUserNamePasswordValidatorType="Service1.Service1UsernamePasswordValidator, Service1"/>
        <serviceCertificate findValue="TestCert" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName"/>
      </serviceCredentials>
    </behavior>

我收到无法找到我的 x.509 证书的错误消息。 我在 serviceCertificate 属性上做错了什么?

在更新服务参考时获取服务证书以被客户接受的更新 即使我尝试使用序列号,我仍然会收到找不到证书的错误。以下是我的错误的详细信息:

我在“个人”文件夹下的“证书”文件夹中有一个自签名证书。 “友好名称”是“TestCert”。序列号是一个以“7f 79 8a a7...”开头的十六进制数字。证书在我的本地机器上。

我尝试过的属性:

storeLocation="LocalMachine" - 我没有改变这个。证书在我的本地机器上,所有文档都指出,当它存在时,这就是它应该是的值。

storeName="My" - 证书位于“证书”文件夹的“个人”文件夹中。这应该对应于“我的”。我想称它为“个人”太直观了。

x509FindType="FindBySubjectName" - 当“findValue”是证书的名称时,我将此值保留为“..SubjectName”。证书的“友好名称”是“TestCert”。 “FriendlyName”没有选项,但我尝试了“By...DistinguishedName”、“By...TemplateName”。我还将选项设置为“FindBySerialNumber”

findValue="" - 我使用了证书名称 'TestCert' 和 'CN=TestCert' 我尝试复制序列号并将 x509FindType 选项设置为按 SerialNumber 搜索,但出现错误:'无效的十六进制字符串格式”。

为什么这么难?我的个人文件夹中有 2 个证书,一个 - localhost 和一个 - 'TestCert'。应该不难找到。

是自签名证书的问题吗?不是x509证书吗?我如何检查它是否在属性列表中。

难怪安全如此困难!文档不好,按照说明操作不起作用。

【问题讨论】:

  • 当您说客户端应用程序名称时 - 您是指使用 web 服务的应用程序还是 web 服务本身?
  • 是的。我想我可以在客户端应用程序中设置 ClientCredentials 并将 Web 服务中的绑定配置为 wsHttpBinding 并设置 security= 消息。然后 Web 服务中的 PrimaryIdentity.Name 将是我在客户端应用程序中设置的内容。但我得到的值是我的 SQL Server 域和我的​​用户名。
  • 如果我理解正确你想要消费者的名字。您的客户是唯一使用该服务的客户吗?如果是这样,在初始访问时将其添加为参数并将跟踪跟踪发送回客户端......这不起作用吗?
  • 目前,我只有一个测试应用。连接到 Web 服务。但在生产环境中,客户端应用程序可能有很多。连接到网络服务。我不想改变方法的参数列表。

标签: c# web-services security


【解决方案1】:

我问的原因是:客户端只使用网络服务——这意味着客户端和服务之间除了请求之外没有任何连接。因此,无论您是通过查询字符串(必要时加密)还是通过会话变量(很像表单帖子)发送客户端名称,我都可能是错的,但我认为客户端和 Web 服务之间不会有紧密的联系像这样 - 这将违背 Web 服务是松散耦合服务的想法。

【讨论】:

  • 我认为客户端应用程序可以在调用 Web 服务方法之前设置 ClientCredentials。调用该方法时,可以在该方法中检查客户端凭据。
  • 我在原帖中添加了更多关于我希望做什么的细节。
  • 您所描述的方式意味着您要使用活动目录 - 但这需要每个客户端都有一个活动的 Windows 登录。不过我对此不太熟悉。如果您不想使用活动目录,最简单的方法是使用客户端的加密名称设置会话变量。您可以将此会话变量用作票证,如果未设置,则不返回任何内容。
  • 我现在可以在 PrimaryIdentity.Name 字段中获得一个值,但它不是我所期望的客户端应用程序名称,而是我的用户名。我在上一个“更新”下的原始帖子中更完整地解释了它。
  • 这是本地(即服务器的安全)而不是客户端的安全。如果有一个共享身份验证池(如 Active Directory),那么可以在所有连接的服务/服务器/PC 之间共享身份验证。如果不是,则必须按照 HTTP 的正常规则进行,这是一种无状态协议。唯一的其他选择是查看 HTTP 标头 - 这可能包含客户端信息...要获得它非常棘手,但这是可能的。这是保存会话信息的地方...
猜你喜欢
  • 2012-02-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-15
  • 1970-01-01
相关资源
最近更新 更多