What is the best way to do Custom Username Password Authentication in WCF?
I have the following code (based on numerous examples on the web)
public class UserNameValidator : UserNamePasswordValidator
{
/// <summary>
/// Validates the user name and password combination.
/// </summary>
/// <param name="userName">The user name.</param>
/// <param name="password">The password.</param>
public override void Validate(string userName, string password)
{
// validate arguments
if (string.IsNullOrEmpty(userName))
throw new ArgumentNullException("userName");
if (string.IsNullOrEmpty(password))
throw new ArgumentNullException("password");
UserCredential user = InMemoryUserStore.Get(userName);
if (user == null)
{
using (DataAccessAdapter da = new DataAccessAdapter())
{
LinqMetaData db = new LinqMetaData(da);
var newUserCredential = (from u in db.User
whe开发者_开发知识库re u.Username == userName
select new UserCredential
{
UserName = u.Username,
PasswordHash = u.PasswordHash,
PasswordSalt = u.PasswordSalt
}).FirstOrDefault();
if (newUserCredential == null)
{
throw new SecurityTokenException("Unknown username or password");
}
else
{
InMemoryUserStore.Add(newUserCredential);
user = newUserCredential;
}
}
}
//Validate Password
PasswordHash p = new PasswordHash(user.PasswordSalt, user.PasswordHash);
if (!p.Verify(password))
{
throw new SecurityTokenException("Unknown username or password");
}
}
}
Is this the best way of doing it?
Seeing as the Custom Validator is only called once, the InMemoryStore is not needed. The code below is what we are using, and it is working great in production.
public override void Validate(string userName, string password)
{
// validate arguments
if (string.IsNullOrEmpty(userName))
throw new ArgumentNullException("userName");
if (string.IsNullOrEmpty(password))
throw new ArgumentNullException("password");
using (DataAccessAdapter da = new DataAccessAdapter())
{
LinqMetaData db = new LinqMetaData(da);
var userCredential = (from u in db.User
where u.Username == userName
select new UserCredential
{
UserName = u.Username,
PasswordHash = u.PasswordHash,
PasswordSalt = u.PasswordSalt
}).FirstOrDefault();
if (userCredential == null)
{
throw new SecurityTokenException("Unknown username or password");
}
//Validate Password
PasswordHash p = new PasswordHash(userCredential.PasswordSalt, userCredential.PasswordHash);
if (!p.Verify(password))
{
throw new SecurityTokenException("Unknown username or password");
}
}
}
Once the call is authenticated, you can create a Custom Principal using the following:
public bool Evaluate(EvaluationContext evaluationContext, ref object state)
{
// get the authenticated client identity
IIdentity client = GetClientIdentity(evaluationContext);
// add roles etc
....
evaluationContext.Properties["Principal"] = new CustomPrincipal(client, roles.ToArray(), userId, email, client.Name);
return true;
}
精彩评论