说明:要建立的WCF服务的安全验证方式为TransportWithMessageCredential,这意味着建立客户端调用WCF服务时,即要信任服务器端的证书,又要提供用户名和密码。好处第一是安全,第二是可以对服务中的任何方法实现权限控制。
在.NET 2008中新建项目,项目模板选WCF服务应用程序。
在项目中添加对System.IdentityModel的引用。
在项目中添加一个新类,该类可以做用户的简单认证或是保存调用服务者的信息,我主要将该类用于后者。类代码如下:
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Text; using System.IdentityModel.Selectors; using System.IdentityModel.Tokens; namespace WcfServiceForMyself { public class UserValidator : UserNamePasswordValidator { string customUserName; string custompassword; public override void Validate(string userName, string password) { if (string.IsNullOrEmpty(userName)) throw new ArgumentNullException("userName"); if (string.IsNullOrEmpty(password)) throw new ArgumentNullException("password"); //这里可加简单的用户判断,如 //if (userName != "Admin" || password != "123") // throw new SecurityTokenException("用户名或者密码错误!"); customUserName = userName; custompassword = password; } public string CustomUserName { get { return customUserName; } } public string CustomPassWord { get { return custompassword; } } } }
服务的接口如下:
using System; using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; using System.ServiceModel; using System.Text; namespace WcfServiceForMyself { // NOTE: If you change the interface name "IServiceForMyself" here, you must also update the reference to "IServiceForMyself" in Web.config. [ServiceContract] public interface IServiceForMyself { [OperationContract] string PrintMessage(string message); } }
服务实现如下:
using System; using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; using System.ServiceModel; using System.Text; using System.IdentityModel.Selectors; using System.IdentityModel.Tokens; namespace WcfServiceForMyself { // NOTE: If you change the class name "ServiceForMyself" here, you must also update the reference to "ServiceForMyself" in Web.config. public class ServiceForMyself : IServiceForMyself { // WcfServiceForMyself.UserValidator myClientUser; public ServiceForMyself() { myClientUser = (WcfServiceForMyself.UserValidator)OperationContext.Current.Host.Credentials.UserNameAuthentication.CustomUserNamePasswordValidator; } public WcfServiceForMyself.UserValidator MyClientUser { get { return myClientUser; } } public string PrintMessage(string msg) { //此时可根据客户端的用户来判断用户是否有权调用接口,如 if (myClientUser.CustomUserName == "Admin") { msg = "输出信息(" + msg + ")"; return msg; } else { return "你没有调用此接口的权限"; } } } }
注意以下Web.Config中的<system.serviceModel>中的配置,如下:
<system.serviceModel> <behaviors> <serviceBehaviors> <behavior name="WcfServiceForMyself.ServiceForMyselfBehavior"> <serviceMetadata httpsGetEnabled="true" /> <serviceDebug includeExceptionDetailInFaults="false" /> <serviceCredentials> <issuedTokenAuthentication allowUntrustedRsaIssuers="true"></issuedTokenAuthentication> <clientCertificate> <authentication certificateValidationMode="None"/> </clientCertificate> <serviceCertificate findValue="10.11.41.87" storeLocation="LocalMachine" x509FindType="FindBySubjectName" storeName="My"/> <userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="WcfServiceForMyself.UserValidator,WcfServiceForMyself"/> </serviceCredentials> </behavior> </serviceBehaviors> </behaviors> <services> <service behaviorConfiguration="WcfServiceForMyself.ServiceForMyselfBehavior" name="WcfServiceForMyself.ServiceForMyself"> <endpoint address="" binding="basicHttpBinding" contract="WcfServiceForMyself.IServiceForMyself" bindingConfiguration="myUserSafeBinding"> <identity> <dns value="10.11.41.87" /> </identity> </endpoint> <endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange" /> </service> </services> <bindings> <basicHttpBinding> <binding name="myUserSafeBinding"> <security mode="TransportWithMessageCredential"> <transport clientCredentialType="Windows"/> <message clientCredentialType="UserName"/> </security> </binding> </basicHttpBinding> </bindings> </system.serviceModel>
我建立的这个WCF服务是想要在silverlight3中应用的,所以用的是basicHttpBinding方式。
好了,服务完成了,发布到IIS中,发布后将该服务按下图配置:
在安全通信中点击编辑,选择如下:
确定后完成配置,OK,服务端的程序完成。