您的位置:首页 > 其它

WCF基于用户名和密码安全成功测试

2012-12-10 09:14 218 查看
目标:
1.客户端与服务器端通信使用x509证书验证,但不用客户端安装证书。只需要服务器端配置好证书即可。
2.验证使用用户名密码形式。

操作:
(这里的测试使用wcf项目模板缺省的服务,即只要新建一个使用vs2008自动生成的wcf项目就行了,

它会自动生成有一个GetData方法,我就用这个方法进行测试)
1.新建WCF服务应用程序.

1.1生成一个服务器证书:运行Visual Studio 2008 命令提示工具:

输入:makecert -r -pe -n "CN=MyServer" -sr LocalMachine -ss My -sky exchange执行。

-sr LocalMachine 请一定保存到LodcalMachine中.目的就是到时如果你部署这个wcf服务的时候可以让IIS找到证书,

反之,IIS会报找不到x509证书.

2.配置web.config文件:
这里要注意的是把storeLocation设为LocalMachine,原因也是到时需要部署的时候可以免掉很多麻烦,因为以后发布到iis时很可以不能正常验证到证书的私钥.

1:  <system.serviceModel>


2:      <bindings>


3:        <wsHttpBinding>


4:          <binding name="NewBinding0">


5:            <security>


6:              <message clientCredentialType="UserName" />


7:            </security>


8:          </binding>


9:        </wsHttpBinding>


10:      </bindings>


11:      <services>


12:        <service behaviorConfiguration="WcfService2.Service1Behavior"


13:          name="WcfService2.Service1">


14:          <endpoint address="" binding="wsHttpBinding" bindingConfiguration="NewBinding0"


15:            contract="WcfService2.IService1">


16:          </endpoint>


17:          <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />


18:        </service>


19:      </services>


20:      <behaviors>


21:        <serviceBehaviors>


22:          <behavior name="WcfService2.Service1Behavior">


23:            <serviceMetadata httpGetEnabled="true" />


24:            <serviceDebug includeExceptionDetailInFaults="false" />


25:            <serviceCredentials>


26:              <clientCertificate>


27:                <authentication certificateValidationMode="None" />


28:              </clientCertificate>


29:              <serviceCertificate findValue="MyServer" storeLocation="LocalMachine" x509FindType="FindBySubjectName" />


30:              <userNameAuthentication userNamePasswordValidationMode="Custom"


31:                customUserNamePasswordValidatorType="WcfService2.MyUserNamePasswordValidator,WcfService2" />


32:            </serviceCredentials>


33:          </behavior>


34:        </serviceBehaviors>


35:      </behaviors>


36:    </system.serviceModel>


3.建造验证客户端用户名和密码的方法.

这里注意的是必须与web.config文件中的customUserNamePasswordValidatorType=中的内容一致,

格式是:"命名空间.方法名,命名空间"

实际项目应用中这里应该是从数据库里确认用客是否合法。

1:  namespace WcfService2


2:  {


3:      public class MyUserNamePasswordValidator : UserNamePasswordValidator


4:      {


5:          public override void Validate(string userName, string password)


6:          {


7:              if (userName != "jac" || password != "jac")


8:              {


9:                  throw new SecurityTokenException("Unknown Username or Password");


10:              }


11:          }


12:      }


13:  }


至此,wcf服务配置完成。

4.新建一个asp.net项目,并添加服务引用这个wcf服务.

5.修改asp.net项目的web.config文件(一定要在引用wcf服务后).

添加一个endpointBehaviors:

1:  <behaviors>


2:    <endpointBehaviors>


3:      <behavior name="jacBehavior">


4:        <clientCredentials>


5:          <serviceCertificate>


6:            <authentication certificateValidationMode="None" />


7:          </serviceCertificate>


8:        </clientCredentials>


9:      </behavior>


10:    </endpointBehaviors>


11:  </behaviors>


然后让它生效,

1:  <endpoint address="http://j-8de9be98d1184/Service1.svc" behaviorConfiguration="jacBehavior"


2:   binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IService1"


3:   contract="ServiceReference1.IService1" name="WSHttpBinding_IService1">


以下是完整的asp.net客户端的web.config文件的system.serviceModel部份

1:  <system.serviceModel>


2:    <behaviors>


3:      <endpointBehaviors>


4:        <behavior name="jacBehavior">


5:          <clientCredentials>


6:            <serviceCertificate>


7:              <authentication certificateValidationMode="None" />


8:            </serviceCertificate>


9:          </clientCredentials>


10:        </behavior>


11:      </endpointBehaviors>


12:    </behaviors>


13:    <bindings>


14:      <wsHttpBinding>


15:        <binding name="WSHttpBinding_IService1" closeTimeout="00:01:00"


16:         openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"


17:         bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard"


18:         maxBufferPoolSize="524288" maxReceivedMessageSize="65536" messageEncoding="Text"


19:         textEncoding="utf-8" useDefaultWebProxy="true" allowCookies="false">


20:          <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"


21:           maxBytesPerRead="4096" maxNameTableCharCount="16384" />


22:          <reliableSession ordered="true" inactivityTimeout="00:10:00"


23:           enabled="false" />


24:          <security mode="Message">


25:            <transport clientCredentialType="Windows" proxyCredentialType="None"


26:             realm="" />


27:            <message clientCredentialType="UserName" negotiateServiceCredential="true"


28:             algorithmSuite="Default" establishSecurityContext="true" />


29:          </security>


30:        </binding>


31:      </wsHttpBinding>


32:    </bindings>


33:    <client>


34:      <endpoint address="http://j-8de9be98d1184/Service1.svc" behaviorConfiguration="jacBehavior"


35:       binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IService1"


36:       contract="ServiceReference1.IService1" name="WSHttpBinding_IService1">


37:        <identity>


38:          <certificate encodedValue="AwAAAAEA.....................eGtnWJsvtFQsEuzDYw==" />


39:        </identity>


40:      </endpoint>


41:    </client>


42:  </system.serviceModel>


6.调用.

1:  ServiceReference1.Service1Client sc = new WebApplication1.ServiceReference1.Service1Client();


2:  sc.ClientCredentials.UserName.UserName = "jac";


3:  sc.ClientCredentials.UserName.Password = "jac";


4:  Label1.Text = sc.GetData(22);


完成.

工程文件下载:http://FunSL.com

为了便使这种方式自由度更高,以下是服务器端的纯代码版本:

1:  using System;


2:  using System.Collections.Generic;


3:  using System.Linq;


4:  using System.Text;


5:  using System.ServiceModel;


6:  using System.IdentityModel.Selectors;


7:  using System.ServiceModel.Description;


8: 


9:  namespace wcf.username


10:  {


11:      class Program


12:      {


13:          static void Main(string[] args)


14:          {


15:              EndpointAddress endp = new EndpointAddress("http://localhost/myservice");


16: 


17:              WSHttpBinding ws = new WSHttpBinding();


18:              ws.Security.Mode = SecurityMode.Message;


19:              ws.Security.Message.ClientCredentialType = MessageCredentialType.UserName;


20: 


21:              ServiceMetadataBehavior behavior = new ServiceMetadataBehavior();


22:              behavior.HttpGetEnabled = true;


23:              behavior.HttpGetUrl = new Uri("http://localhost/myservice/mex");


24: 


25:              ServiceHost sh = new ServiceHost(typeof(serverdo), new Uri(endp.ToString()));


26: 


27:              sh.Description.Behaviors.Add(behavior);


28: 


29:              sh.Credentials.ClientCertificate.Authentication.CertificateValidationMode =


30:                  System.ServiceModel.Security.X509CertificateValidationMode.None;


31: 


32: 


33:              sh.Credentials.UserNameAuthentication.UserNamePasswordValidationMode =


34:                   System.ServiceModel.Security.UserNamePasswordValidationMode.Custom;


35: 


36:              sh.Credentials.UserNameAuthentication.CustomUserNamePasswordValidator = new checkUserName();


37: 


38:              sh.Credentials.ServiceCertificate.SetCertificate(


39:                  System.Security.Cryptography.X509Certificates.StoreLocation.LocalMachine,


40:                  System.Security.Cryptography.X509Certificates.StoreName.My,


41:                  System.Security.Cryptography.X509Certificates.X509FindType.FindBySubjectName, "MyServer");


42: 


43:              sh.AddServiceEndpoint(typeof(Iservice), ws, endp.ToString());


44:              sh.Open();


45: 


46:              Console.WriteLine("ok");


47:              Console.Read();


48:          }


49:      }


50: 


51:      class checkUserName:UserNamePasswordValidator


52:      {


53:          public override void Validate(string userName, string password)


54:          {


55:              if (userName != "jac" && password != "jac")


56:              {


57:                  throw new FaultException("userName and passWord be error");


58:              }


59:          }


60:      }


61: 


62:      [ServiceContract]


63:      interface Iservice


64:      {


65:          [OperationContract]


66:          string test(string msg);


67:      }


68: 


69:      class serverdo:Iservice


70:      {


71:          #region Iservice 成员


72: 


73:          public string test(string msg)


74:          {


75:              Console.WriteLine("user inter:" + msg);


76: 


77:              return "user inter:" + msg;


78:          }


79: 


80:          #endregion


81:      }


82: 


83:  }
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐