Каков наилучший способ сделать аутентификацию по имени пользователя по имени пользователя в WCF? - PullRequest
1 голос
/ 04 мая 2011

У меня есть следующий код (на основе многочисленных примеров в сети)

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
                                         where 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");
        }
    }
}

Это лучший способ сделать это?

1 Ответ

1 голос
/ 06 мая 2011

Поскольку пользовательский валидатор вызывается только один раз, хранилище InMemoryStore не требуется.Код ниже - это то, что мы используем, и он отлично работает в производстве.

    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");
            }
        }
    }

Как только вызов аутентифицирован, вы можете создать пользовательский принципал, используя следующее:

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;
    }
...