如何从客户端请求获取X509Certificate

时间:2011-09-23 11:46:21

标签: c# wcf web-services wcf-security x509certificate

我有一个使用证书保护的网络服务。 现在,我想通过查看证书指纹来识别客户端。这意味着我的服务上的指纹列表已链接到某个用户。

实际上,我的第一个问题(有点偏离主题)是:这是一个好方法还是我还应该引入一些用户名密码构造?

第二个问题是:如何获取客户端用于连接到Web服务的证书,以便我可以在服务端读取指纹。

我确实读了很多关于它的内容(比如这篇帖子:How do I get the X509Certificate sent from the client in web service?)但找不到答案。

我没有HTTPContext,所以这不是一个选项。在上面提到的帖子中提到了Context.Request.ClientCertificate.Certificate,但我想它们也意味着HTTPContext。另外,将<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />添加到web.config也不是一种选择。

2 个答案:

答案 0 :(得分:20)

这就是我们在webservice的构造函数中执行此操作的方法:

if (OperationContext.Current.ServiceSecurityContext.AuthorizationContext.ClaimSets == null)
    throw new SecurityException ("No claimset service configured wrong");

if (OperationContext.Current.ServiceSecurityContext.AuthorizationContext.ClaimSets.Count <= 0)
    throw new SecurityException ("No claimset service configured wrong");


var cert = ((X509CertificateClaimSet) OperationContext.Current.ServiceSecurityContext.
            AuthorizationContext.ClaimSets[0]).X509Certificate;

//this contains the thumbprint
cert.Thumbprint

答案 1 :(得分:4)

我不认为这种方法有任何问题,只要在您可以控制证书分发并确保它们安全存储的环境中使用此服务。

假设这是一个WCF服务,您可以使用继承自ServiceAuthorizationManager的类来获取客户端提供的证书。这样的事情会起到作用:

public class CertificateAuthorizationManager : ServiceAuthorizationManager
{
    protected override bool CheckAccessCore(OperationContext operationContext)
    {
        if (!base.CheckAccessCore(operationContext))
        {
            return false;
        }

        string thumbprint = GetCertificateThumbprint(operationContext);

        // TODO: Check the thumbprint against your database, then return true if found, otherwise false
    }

    private string GetCertificateThumbprint(OperationContext operationContext)
    {
        foreach (var claimSet in operationContext.ServiceSecurityContext.AuthorizationContext.ClaimSets)
        {
            foreach (Claim claim in claimSet.FindClaims(ClaimTypes.Thumbprint, Rights.Identity))
            {
                string tb = BitConverter.ToString((byte[])claim.Resource);
                tb = tb.Replace("-", "");
                return tb;
            }
        }

        throw new System.Security.SecurityException("No client certificate found");
    }
}

然后,您需要在服务器上更改配置以使用此授权管理器:

<system.serviceModel>

    <behaviors>
        <serviceBehaviors>
            <behavior name="MyServerBehavior">

                <serviceAuthorization serviceAuthorizationManagerType="myNamespace.CertificateAuthorizationManager, myAssembly"/>

                ...

            </behavior>
        </serviceBehaviors>
    </behaviors>

    ...

</system.serviceModel>