65.9K
CodeProject 正在变化。 阅读更多。
Home

Id密码、自定义验证的自托管安全 WCF

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.90/5 (14投票s)

2012年8月2日

CPOL

1分钟阅读

viewsIcon

43912

downloadIcon

200

无需配置文件 – 所有设置都在代码中,无需 IIS – 自托管,通过通道工厂消费

引言

自托管安全 WCF 自定义验证,无需配置文件 – 所有设置都在代码中,无需 IIS – 自托管,通过通道工厂消费

 

背景

最近我遇到了一种情况,需要在没有 IIS 的环境中创建一个安全的 WCF POC,并且我们只有 VS 2010 Express。我们需要创建一个完全自给自足的 POC,因此不需要证书。

解决方案是创建一个自托管的 WCF 服务,使用自定义验证并使用通道工厂进行消费。在创建这个 POC 的过程中,我遇到了一些错误,然后开始在互联网上搜索类似的 POC,我找到了一些,但大多数都不能直接运行,例如只有服务器端代码,只有客户端,或者需要在 app.config 中进行一些修改。 

 

WCF 服务器端 

 

自托管(控制台)WCF 服务,传输安全(ID/密码) 

using System;
using System.ServiceModel;
using System.ServiceModel.Security;
using System.IdentityModel.Tokens;
using System.IdentityModel.Selectors;
using System.Security.Principal;
using System.ServiceModel.Description;
 
namespace SecurWCFSelfHosting
{
    class Program
    {
        [ServiceContract]
        public interface IDemoService
        {
            [OperationContract]
            int Add(int x, int y);
        }
 
        public class DemoService : IDemoService
        {
           public int Add(int x, int y)
            {
                return x + y;
            }
        }

        static void Main(string[] args)
        {
        
            // This is a address of our service
            Uri httpUrl = new Uri("https://:999/MyService/");
            //Create ServiceHost
            ServiceHost host = new ServiceHost(typeof(DemoService), httpUrl);
            
            /// Set behaviour of **binding**
            BasicHttpBinding http = new BasicHttpBinding();
            //1. set Mode TransportCredentialOnly = no httpS 
            http.Security.Mode = BasicHttpSecurityMode.TransportCredentialOnly;
            //2. Transport security Basic = user id and password
            http.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;
            
             
            ///** Set behaviour of **host**
            //Add a service endpoint
            host.AddServiceEndpoint(typeof(IDemoService), http, "");
            host.Credentials.UserNameAuthentication.UserNamePasswordValidationMode = UserNamePasswordValidationMode.Custom;
            host.Credentials.UserNameAuthentication.CustomUserNamePasswordValidator = new MyCustomValidator();
 
            // checking and publishing meta data
            ServiceMetadataBehavior smb = host.Description.Behaviors.Find<ServiceMetadataBehavior>();
            if (smb == null)
            {
                smb = new ServiceMetadataBehavior();
                smb.HttpGetEnabled = true;
                host.Description.Behaviors.Add(smb);
            }
            
            //Start the Service
            host.Open();
 
            Console.WriteLine(DateTime.Now.ToString()+" Service is host at " + httpUrl.ToString());
            Console.WriteLine("The service is running in the following account: {0}", WindowsIdentity.GetCurrent().Name);
            Console.WriteLine("Press <ENTER> to terminate service.");
            Console.ReadLine(); 
        }
    }
 
    public class MyCustomValidator : UserNamePasswordValidator
    {
        public override void Validate(string userName, string password)
        {
            //For Demo only here you can add logic to validate ID,Pwd in AD or DB
            if ((userName != "h") || (password != "p"))
            {
                throw new SecurityTokenException("Him:) Validation Failed!");
            }
            Console.WriteLine(DateTime.Now.ToString()+" Validation success for user :"+ userName);
        }
    }
}
 
 

 

客户端 

 

在控制台应用程序中消费,使用通道工厂 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Description;
 
/// svcuti. @ C:\Program Files\Microsoft SDKs\Windows\v7.0A\bin

namespace WCFConsumeByChannelFactory
{
    class Program
    {
        static void Main(string[] args)
        {
 
            EndpointAddress Serviceaddress = new EndpointAddress("https://:999/MyService/");
 
            /// Set behaviour of **binding** Same setting as ##Server##
            BasicHttpBinding httpBinding = new BasicHttpBinding();
            httpBinding.Security.Mode = BasicHttpSecurityMode.TransportCredentialOnly;
            httpBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;
            
            ChannelFactory<IDemoService> myChannelFactory =
                new ChannelFactory<IDemoService>(httpBinding, Serviceaddress);
            var defaultCredentials = myChannelFactory.Endpoint.Behaviors.Find<ClientCredentials>();
 
            //#1 IF this dosen not work then try #2
            myChannelFactory.Credentials.UserName.UserName = "h";
            myChannelFactory.Credentials.UserName.Password = "p";
 
            ///#2
            //ClientCredentials CC = new ClientCredentials();
            //CC.UserName.UserName = "h";
            //CC.UserName.Password = "p";
            // myChannelFactory.Endpoint.Behaviors.Remove(defaultCredentials); //remove default ones
            // myChannelFactory.Endpoint.Behaviors.Add(CC); //add required on

            // Create a channel.
            IDemoService wcfClient1 = myChannelFactory.CreateChannel();
 
            double s = wcfClient1.Add(73, 22);
            Console.WriteLine(s.ToString());
            ((IClientChannel)wcfClient1).Close();
 
            Console.ReadKey();
 
        }
    }
}
 
 

所有这些代码都包含在附件的 zip 文件中。

 

关注点

在互联网上搜索时,我找到了这个:如何:使用通道工厂异步调用操作  http://msdn.microsoft.com/en-us/library/bb885132.aspx

绑定摘要

 

http://wcfsecurityguide.codeplex.com/releases/view/15892 

 

© . All rights reserved.