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
{
    public interface IServerCallClient
    {

        [ OperationContract ]
        IPEndPoint ServerRequestClientIP ();

        [ OperationContract ]
        void ServerSayMsg ( string text);
    }
}

服务接口

using System ;
using System . ServiceModel ;

namespace WcfService1
{
    [ ServiceContract (CallbackContract = typeof ( IServerCallClient ))]
    public interface IClientCallServer
    {
        [ OperationContract ]
        void ClientSayToServer ( string text);
        [ OperationContract ]
        DateTime ClientRequestDateTime ();
    }
}

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 )]
    public class ClientCallServer : IClientCallServer , IDisposable
    {
        Timer timer = new Timer ();

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

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

        public static List < IServerCallClient > ServerCallClient = new List < IServerCallClient >();
        public DateTime ClientRequestDateTime ()
        {
            return DateTime . Now ;
        }

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

        public void Dispose ()
        {
            ServerCallClient . Clear ();
        }
    }
}

身份认证

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

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

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

Web配置文件

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

  <system.web>
    <compilation debug = "true" targetFramework = "4.0" />
  </system.web>
  <system.serviceModel>
    <services>
      <service name = "WcfService1.ClientCallServer" >
        <endpoint address = "" binding = "wsDualHttpBinding" bindingConfiguration = "NewBinding0"
          contract = "WcfService1.IClientCallServer" >
        </endpoint>
      </service>
    </services>
    <bindings>
      <wsDualHttpBinding>
        <binding name = "NewBinding0" >
          <security mode = "Message" ><--消息加密->
            <message clientCredentialType = "UserName" />
          </security>
        </binding>
      </wsDualHttpBinding>
    </bindings>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <serviceCredentials>
  <--findValue 公司名称=GreenWhale,storeLocation==存储位置本机,储存位置:Root(根证书区)->
            <serviceCertificate findValue = "CN=GreenWhale" x509FindType = "FindBySubjectDistinguishedName" storeLocation = "LocalMachine" storeName = "Root" ></serviceCertificate>
            <clientCertificate>
              <authentication certificateValidationMode = "None" ></authentication>
            </clientCertificate>
<---customUserNamePasswordValidatorType,先放动态库的命名空间+类名,然后时逗号然后是dll名称,我这里时WcfService1--->
            <userNameAuthentication userNamePasswordValidationMode = "Custom" includeWindowsGroups = "false" customUserNamePasswordValidatorType = "WcfService1.WCFValidator,WcfService1" ></userNameAuthentication>
          </serviceCredentials>
          <!-- 为避免泄漏元数据信息,请在部署前将以下值设置为 false -->
          <serviceMetadata httpGetEnabled = "true" />
          <!-- 要接收故障异常详细信息以进行调试,请将以下值设置为 true。在部署前设置为 false 以避免泄漏异常信息 -->
          <serviceDebug includeExceptionDetailInFaults = "false" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment aspNetCompatibilityEnabled = "false"
      multipleSiteBindingsEnabled = "true" />
  </system.serviceModel>
<system.webServer>
    <modules runAllManagedModulesForAllRequests = "true" />
    <!--
        若要在调试过程中浏览 Web 应用程序根目录,请将下面的值设置为 True。
        在部署之前将该值设置为 False 可避免泄露 Web 应用程序文件夹信息。
      -->
    <directoryBrowse enabled = "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
{
    public partial class Form1 : Form , IClientCallServerCallback
    {
        public Form1 ()
        {
            InitializeComponent ();
            context = new InstanceContext ( this );
            client = new ClientCallServerClient ( context );
        }
        public IPEndPoint ServerRequestClientIP ()
        {
            throw new NotImplementedException ();
        }
        InstanceContext context;
        public void ServerSayMsg ( string text)
        {
            MessageBox . Show ( text );
        }
        ClientCallServerClient client;
        private void button1_Click ( object sender, EventArgs e)
        {
          //  certificateValidationMode
            client . ClientCredentials . UserName . UserName = "1234" ;
            client . ClientCredentials . UserName . Password = "1234" ;
            client . ClientSayToServer ( "Fuck" );
        }
    }
}


  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值