Reputation: 7281
I create a simple wcf with custom authentication and authorization
<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>
With this implementation :
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;
}
}
And
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");
}
}
}
I upload my service under ssl in my local iis and call my service in my client like this:
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 = "[email protected]";
objData.Age = 20;
string message = serviceProxy.GetData(5);
//Console.WriteLine(serviceProxy.UpdatePatientData(objData));
Console.WriteLine(message);
Console.ReadLine();
}
With this config :
<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>
But as you can see my user name is test
and password is test123
,but when i change my password in the client side everything works fine and the data is returned again ?!!!why ?
Upvotes: 1
Views: 184
Reputation: 2460
Maybe throw an exception if the username and password don't match in your validate method:
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");
}
}
or more simplified:
public override void Validate(string userName, string password)
{
if (userName != "test" && password != "test123")
{
throw new FaultException("Unknown Username or Incorrect Password");
}
}
Its also good to check for nulls:
if (null == userName || null == password)
{
throw new ArgumentNullException();
}
Upvotes: 1