WCF身份验证和授权不起作用

时间:2017-05-20 14:46:21

标签: c# web-services rest wcf

我使用自定义身份验证和授权创建一个简单的wcf

<system.serviceModel>
    <client />
    <bindings>
      <basicHttpBinding>
        <binding name="secureHttpBinding">
          <security mode="TransportWithMessageCredential">
            <message clientCredentialType="UserName" />
          </security>
        </binding>
      </basicHttpBinding>
    </bindings>
    <services>
      <service name="WcfService1.Service1" behaviorConfiguration="customBehaviour">
        <endpoint address=""
                  binding="basicHttpBinding"
                  bindingConfiguration="secureHttpBinding"
                  contract="WcfService1.IService1"/>

        <endpoint address="mex"
                  binding="mexHttpsBinding"
                  contract="IMetadataExchange" />
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <serviceMetadata httpGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="false"/>
        </behavior>
        <behavior name="customBehaviour">

          <serviceMetadata httpGetEnabled="true"/>

          <serviceDebug includeExceptionDetailInFaults="true"/>
          <serviceCredentials>
            <userNameAuthentication userNamePasswordValidationMode="Custom"
               customUserNamePasswordValidatorType="WcfService1.UserAuthentication,WcfService1"/>
          </serviceCredentials>

          <serviceAuthorization principalPermissionMode="Custom">
            <authorizationPolicies>
              <add policyType="WcfService1.AuthorizationPolicy, WcfService1" />
            </authorizationPolicies>
          </serviceAuthorization>


        </behavior>
      </serviceBehaviors>
    </behaviors>
    <protocolMapping>
        <add binding="basicHttpsBinding" scheme="https" />
    </protocolMapping>    
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
  </system.serviceModel>

有了这个实现:

public class AuthorizationPolicy: IAuthorizationPolicy
    {
        string id = Guid.NewGuid().ToString();

        public string Id
        {
            get { return this.id; }
        }

        public ClaimSet Issuer
        {
            get { return ClaimSet.System; }
        }

        public bool Evaluate(EvaluationContext context, ref object state)
        {
            object obj;
            if (!context.Properties.TryGetValue("Identities", out obj))
                return true;

            IList<IIdentity> identities = obj as IList<IIdentity>;
            if (obj == null || identities.Count <= 0)
                return true;

            context.Properties["Principal"] = new CustomPrincipal(identities[0]);
            return true;
        }
    }
    class CustomPrincipal : IPrincipal
    {
        IIdentity identity;
        public CustomPrincipal(IIdentity identity)
        {
            this.identity = identity;
        }

        public IIdentity Identity
        {
            get { return this.identity; }
        }

        public bool IsInRole(string role)
        {

            return true;
        }
    }

并且

public class UserAuthentication : UserNamePasswordValidator
    {
        public override void Validate(string userName, string password)
        {
            try
            {
                if (userName == "test" && password == "test123")
                {
                    Console.WriteLine("Authentic User");
                }
            }
            catch (Exception ex)
            {
                throw new FaultException("Unknown Username or Incorrect Password");
            }
        }
    }

我在本地iis上的ssl下上传服务,并在我的客户端中调用我的服务:

 static void Main(string[] args)
        {
            ServiceReference1.Service1Client serviceProxy = new ServiceReference1.Service1Client();
            serviceProxy.ClientCredentials.UserName.UserName = "test";
            serviceProxy.ClientCredentials.UserName.Password = "test123";

            PatientData objData = new PatientData();
            objData.Name = "test";
            objData.Gender = "Male";
            objData.Email = "v@g.com";
            objData.Age = 20;
            string message = serviceProxy.GetData(5);
            //Console.WriteLine(serviceProxy.UpdatePatientData(objData));


            Console.WriteLine(message);
            Console.ReadLine();
        }

使用此配置:

<system.serviceModel>
    <bindings>
        <basicHttpBinding>
            <binding name="BasicHttpBinding_IService1">
                <security mode="TransportWithMessageCredential" />
            </binding>
        </basicHttpBinding>
    </bindings>
    <client>
        <endpoint address="https://union-pc58.union.com/Service1.svc"
            binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IService1"
            contract="ServiceReference1.IService1" name="BasicHttpBinding_IService1" />
    </client>
</system.serviceModel>

但正如您可以看到我的用户名是test而密码是test123,但是当我在客户端更改密码时,一切正常并且数据会再次返回?!!!为什么?

1 个答案:

答案 0 :(得分:1)

如果您的验证方法中的用户名和密码不匹配,可能会抛出异常:

public override void Validate(string userName, string password)
{
    try
    {
        if (userName == "test" && password == "test123")
        {
            Console.WriteLine("Authentic User");
        } else {
            throw new Exception();
        }
    }
    catch (Exception ex)
    {
        throw new FaultException("Unknown Username or Incorrect Password");
    }
}

或更简化:

public override void Validate(string userName, string password)
{   
    if (userName != "test" && password != "test123")
    {
        throw new FaultException("Unknown Username or Incorrect Password");     
    }
}

检查空值也很好:

if (null == userName || null == password)
   {
       throw new ArgumentNullException();
   }