c# - 使用证书以编程方式实现 WCF

标签 c# web-services wcf authentication certificate

我是 WCF 的新手,正在努力了解安全性。我仍在阅读和学习,但我已经到了一个可以使用证书身份验证的 WCF 工作版本的地步。我知道代码有一些弱点;但是,我最初的目标是使用证书身份验证创建通信。此外,我想以编程方式创建所有内容(没有针对服务或客户端的 Web.config 配置)。这样做的原因是客户端应该能够链接一个程序集(类库)并访问服务器。此外,我正在从文件系统加载证书(同样,我知道这不安全)。我想得到一点反馈。

以下客户端代码段正在创建一个我可以用来连接到服务器的对象。匿名类型 T 是我的服务接口(interface),例如I服务。

这是我的客户端实现:

var url = "URL TO WS";
var binding = new WSHttpBinding
{
    Security =
    {
        Mode = SecurityMode.Message,
        Message = {ClientCredentialType = MessageCredentialType.Certificate}
    }
};

var endpoint = new EndpointAddress(url);
var channelFactory = new ChannelFactory<T>(binding, endpoint);

if (channelFactory.Credentials != null)
{
    channelFactory.Credentials.ClientCertificate.Certificate =
        new X509Certificate2(@"PATH\TO\Client.pfx"); // Client Certificate PRIVATE & PUBLIC Key
    channelFactory.Credentials.ServiceCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.None; // I know this is not good, but I dont have a valid certificate from a trusted entity
}

wcfClient = channelFactory.CreateChannel();
return wcfClient;

服务有点复杂。我使用 .svc 文件及其代码隐藏。如果我正确理解 .svc 文件的使用,那么我相信这是 .NET 框架创建 ServiceHost 并自动打开它的入口点?在我的实现中,我没有打开 ServiceHost,我只实现了一个 ServiceHostFactoryBase 并在 .svc 标记语言中引用它。查看工厂部分 - 这是我实现自定义主机工厂的部分。

<%@ ServiceHost Language="C#" Debug="true"
    Service="Service.Services.LevelService" CodeBehind="LevelService.svc.cs" 
    Factory="Service.Security.ServiceHostFactory.HostFactory" %>

我的自定义 Host Factory 如下所示:

public class HostFactory : ServiceHostFactoryBase
{
    public override ServiceHostBase CreateServiceHost(string constructorString, Uri[] baseAddresses)
    {
        var serviceType = Type.GetType(constructorString);

        if (serviceType.GetInterfaces().Count() != 1)
            throw new NotImplementedException("The service can only have one implemented interface");

        var interfaceType = serviceType.GetInterfaces()[0];

        var myServiceHost = new ServiceHost(serviceType, baseAddresses);

        var httpBinding = new WSHttpBinding();
        httpBinding.Security.Message.ClientCredentialType = MessageCredentialType.Certificate;
        httpBinding.Security.Mode = SecurityMode.Message;

        myServiceHost.Credentials.ServiceCertificate.Certificate = new X509Certificate2(@"PATH\TO\Server.pfx");
        myServiceHost.Credentials.ClientCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.Custom;
        myServiceHost.Credentials.ClientCertificate.Authentication.CustomCertificateValidator = new MyX509CertificateValidator();
        myServiceHost.Credentials.ClientCertificate.Certificate = new X509Certificate2(@"PATH\TO\Client.cer");
        myServiceHost.AddServiceEndpoint(interfaceType, httpBinding, String.Empty);

        return myServiceHost;
    }
}

自定义验证器还没有做很多事情,但在这里也是如此:

public class MyX509CertificateValidator : X509CertificateValidator
{
    public override void Validate(X509Certificate2 certificate)
    {
        // Check that there is a certificate.
        if (certificate == null)
        {
            throw new ArgumentNullException("certificate");
        }

        // Check that the certificate issuer matches the configured issuer.
        //throw new SecurityTokenValidationException("Certificate was not issued by a trusted issuer");
    }
}

如果我没理解错的话,服务器只有客户端注册的公钥,因为我只引用了 .cer 文件。

现在我的大问题是,如果我想在生产服务器上获得类似的东西 - 假设没有人会真正获得可执行文件(包括证书),这是否是一个让不受欢迎的人远离的可能解决方案我的网络服务?基本上,我不希望任何其他人使用我的网络服务——前提是您拥有适当的证书。另外,我在客户端设置的部分有多少问题:

CertificateValidationMode = X509CertificateValidationMode.None

我知道有很多问题 - 但总的来说,我想知道我在这个实现中是否犯了一些基本错误。

最佳答案

好的,

在阅读了大量教程和演示应用程序之后,我发现最好的方法是在 Windows 上使用证书存储。但是,我仍然可以考虑一种混合解决方案,其中服务器在证书存储区中拥有证书,而客户端将其嵌入到资源中。如果您正在为 WCF 和证书苦苦挣扎,请查看这些链接:

IIS7 Permissions Overview - ApplicationPoolIdentity

我能够创建传输和消息安全的 WCF Web 服务。我建议阅读链接的文章,因为有很多信息可以让您了解证书及其用法。特别是在处理自签名证书时!

我最终使用消息安全模式 + 带有 ChainTrust 的客户端证书实现了 wsHttpBinding。

希望这对其他人有帮助!

关于c# - 使用证书以编程方式实现 WCF,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31685988/

相关文章:

c# - 我可以称之为依赖注入(inject)吗?

C# Lambda 表达式通过逗号分隔的 id 提取所有名称

c# - 找不到具有名称和契约(Contract)的端点元素

c# - 在 WCF/WIF 中如何合并来自两个不同客户端的自定义 sts token 的声明

c# - WCF 是这个通用 SOAP 消息的正确方法吗?

c# - 通过 SOAP 使用 SharePoint Web 服务进行 Windows 身份验证

c# - 将动态添加的文本框中的数据添加到数据库

c# - 无法使用 https 端点创建 wcf web 服务

java - 如何使用 Restful Web 服务反序列化 xml 集合表示

java - Rest Web 服务(post)使用 json 不起作用