WCF双工通讯+身份认证

证书

  以管理员身份打开VS开发人员命令提示符工具
然后输入如下字符串
  makecert -sr localmachine -ssRoot -n CN=GreenWhale -sky exchange -pe -r。
回车返回Success即可。

然后打开“C:\Windows\System32\en-US\certlm.msc”  Zh-CN也可 “C:\Windows\System32\zh-CN\certlm.msc

别打错了是这个“certmgr.msc”

然后就可以看到证书了,导出证书,软件发布后让客户端安装此证书即可。

服务端


 服务端回调接口:

using System.ServiceModel;
using System.Net;
namespace WcfService1
{
    publicinterface IServerCallClient
    {

        [OperationContract]
        IPEndPointServerRequestClientIP();

        [OperationContract]
        voidServerSayMsg(string text);
    }
}

服务接口

using System;
using System.ServiceModel;

namespace WcfService1
{
    [ServiceContract(CallbackContract=typeof(IServerCallClient))]
    publicinterface IClientCallServer
    {
        [OperationContract]
        voidClientSayToServer(string text);
        [OperationContract]
        DateTimeClientRequestDateTime();
    }
}

WCF 服务端代码实现

请注意,服务端回调客户端时 客户端的链接必须没有断开,断开了就无法回调了,

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
using System.Timers;

namespace WcfService1
{
    // 注意: 使用“重构”菜单上的“重命名”命令,可以同时更改代码、svc 和配置文件中的类名“Service1”。
    // 注意: 为了启动 WCF 测试客户端以测试此服务,请在解决方案资源管理器中选择 Service1.svc 或 Service1.svc.cs,然后开始调试。
    [ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)]
    publicclass ClientCallServer :IClientCallServer,IDisposable
    {
        Timer timer= newTimer();

        publicClientCallServer()
        {
            timer.Elapsed+= Timer_Elapsed;
            timer.Interval= 5000;
            timer.Start();
        }

        privatevoid Timer_Elapsed(object sender,ElapsedEventArgs e)
        {
            if (ServerCallClient!= null)
            {
                foreach (var itemin ServerCallClient)
                {
                    item.ServerSayMsg("SB");
                }
            }
        }

        publicstatic List<IServerCallClient> ServerCallClient= newList<IServerCallClient>();
        publicDateTime ClientRequestDateTime()
        {
            returnDateTime.Now;
        }

        publicvoid ClientSayToServer(string text)
        {
            var channel= OperationContext.Current.GetCallbackChannel<IServerCallClient>();
            ServerCallClient.Add(channel);
            Debug.WriteLine(OperationContext.Current.SessionId);
            Debug.WriteLine(text);
        }

        publicvoid Dispose()
        {
            ServerCallClient.Clear();
        }
    }
}

身份认证

实现身份认证需要服务端继承System.IdentityModel.Selectors.UserNamePasswordValidator类。同理需要引用System.IdentityModel.Dll;

namespace WcfService1
{
    /// <summary>
    /// WCF身份认证
    /// </summary>
    publicclass WCFValidator : System.IdentityModel.Selectors.UserNamePasswordValidator
    {
        /// <summary>
        /// 身份及密码验证
        /// </summary>
        /// <param name="userName"></param>
        /// <param name="password"></param>
        publicoverride void Validate(string userName,string password)
        {
            if (userName== "1234"&& password== "1234")//身份验证不过则报错,过了就过了。
            {

            }
            else
            {
                thrownew System.IdentityModel.Tokens.SecurityTokenException("Unknown Username or Password");
            }
        }
    }
}

Web配置文件

<?xml version="1.0" encoding="utf-8"?>
<configuration>

  <system.web>
    <compilationdebug="true"targetFramework="4.0"/>
  </system.web>
  <system.serviceModel>
    <services>
      <servicename="WcfService1.ClientCallServer">
        <endpointaddress=""binding="wsDualHttpBinding"bindingConfiguration="NewBinding0"
          contract="WcfService1.IClientCallServer">
        </endpoint>
      </service>
    </services>
    <bindings>
      <wsDualHttpBinding>
        <bindingname="NewBinding0">
          <securitymode="Message"><--消息加密->
            <messageclientCredentialType="UserName"/>
          </security>
        </binding>
      </wsDualHttpBinding>
    </bindings>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <serviceCredentials>
  <--findValue 公司名称=GreenWhale,storeLocation==存储位置本机,储存位置:Root(根证书区)->
            <serviceCertificatefindValue="CN=GreenWhale"x509FindType="FindBySubjectDistinguishedName"storeLocation="LocalMachine"storeName="Root"></serviceCertificate>
            <clientCertificate>
              <authenticationcertificateValidationMode="None"></authentication>
            </clientCertificate>
<---customUserNamePasswordValidatorType,先放动态库的命名空间+类名,然后时逗号然后是dll名称,我这里时WcfService1--->
            <userNameAuthenticationuserNamePasswordValidationMode="Custom"includeWindowsGroups="false"customUserNamePasswordValidatorType="WcfService1.WCFValidator,WcfService1"></userNameAuthentication>
          </serviceCredentials>
          <!-- 为避免泄漏元数据信息,请在部署前将以下值设置为 false -->
          <serviceMetadatahttpGetEnabled="true"/>
          <!-- 要接收故障异常详细信息以进行调试,请将以下值设置为 true。在部署前设置为 false 以避免泄漏异常信息 -->
          <serviceDebugincludeExceptionDetailInFaults="false"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironmentaspNetCompatibilityEnabled="false"
      multipleSiteBindingsEnabled="true"/>
  </system.serviceModel>
<system.webServer>
    <modulesrunAllManagedModulesForAllRequests="true"/>
    <!--
        若要在调试过程中浏览 Web 应用程序根目录,请将下面的值设置为 True。
        在部署之前将该值设置为 False 可避免泄露 Web 应用程序文件夹信息。
      -->
    <directoryBrowseenabled="true"/>
  </system.webServer>

</configuration>


客户端

客户端很简单,首先引用WCF服务,然后在连接时输入对应的账号和密码即可。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net;
using System.ServiceModel;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using WindowsFormsApp1.Service;
namespace WindowsFormsApp1
{
    publicpartial class Form1 :Form, IClientCallServerCallback
    {
        publicForm1()
        {
            InitializeComponent();
            context= newInstanceContext(this);
            client= newClientCallServerClient(context);
        }
        publicIPEndPoint ServerRequestClientIP()
        {
            thrownew NotImplementedException();
        }
        InstanceContext context;
        publicvoid ServerSayMsg(string text)
        {
            MessageBox.Show(text);
        }
        ClientCallServerClient client;
        privatevoid button1_Click(object sender,EventArgs e)
        {
          //  certificateValidationMode
            client.ClientCredentials.UserName.UserName= "1234";
            client.ClientCredentials.UserName.Password= "1234";
            client.ClientSayToServer("Fuck");
        }
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值