Guushuuse .NET

领域驱动设计==哲学

导航

ASP.NET&Spring.NET&NHibernate最佳实践(二十一)——第4章权限子系统(14)

成员资格信息提供类(HibernateMembershipProvider.cs)

        
/// <summary>
        
/// 将用户密码重置为一个自动生成的新密码
        
/// </summary>
        
/// <param name="username"></param>
        
/// <param name="answer"></param>
        
/// <returns></returns>

        public override string ResetPassword(string username, string passwordAnswer)
        
{
            
if (!this.EnablePasswordReset)
            
{
                
throw new NotSupportedException("Not configured to support password resets.");
            }


            SecUtility.CheckParameter(
ref username, truetruetrue255"username");

            
int status;
            
string password;
            MembershipPasswordFormat passwordFormat;
            
string salt;
            
int failedPasswordAttemptCount;
            
int failedPasswordAnswerAttemptCount;
            
bool isApproved;
            DateTime lastLoginDate;
            DateTime lastActivityDate;

            GetPasswordWithFormat(
this._applicationName, username, falseout status, out password, out passwordFormat,
                
out salt, out failedPasswordAttemptCount, out failedPasswordAnswerAttemptCount, out isApproved,
                
out lastLoginDate, out lastActivityDate);

            
if (status == 0)
            
{
                
if (passwordAnswer != null)
                
{
                    passwordAnswer 
= passwordAnswer.Trim();
                }


                
string answer;

                
if (!String.IsNullOrEmpty(passwordAnswer))
                
{
                    answer 
= EncodePassword(passwordAnswer.ToLower(CultureInfo.InvariantCulture), passwordFormat, salt);
                }

                
else
                
{
                    answer 
= passwordAnswer;
                }


                SecUtility.CheckParameter(
ref answer, this._requiresQuestionAndAnswer, this._requiresQuestionAndAnswer, false128"passwordAnswer");

                
string newPassword = GeneratePassword();

                ValidatePasswordEventArgs args 
= new ValidatePasswordEventArgs(username, newPassword, false);
                
this.OnValidatingPassword(args);

                
if (args.Cancel)
                
{
                    
if (args.FailureInformation != null)
                    
{
                        
throw args.FailureInformation;
                    }


                    
throw new ProviderException("Membership custom password validation failure.");
                }


                status 
= ServiceLocator.UserService.ResetPassword(this._applicationName, username, newPassword,
                    
this._maxInvalidPasswordAttempts, this._passwordAttemptWindow, salt, passwordFormat, answer,
                     DateTime.UtcNow);

                
if (status != 0)
                
{
                    
string errText = this.GetExceptionText(status);

                    
if (this.IsStatusDueToBadPassword(status))
                    
{
                        
throw new MembershipPasswordException(errText);
                    }


                    
throw new ProviderException(errText);
                }


            }


            
if (IsStatusDueToBadPassword(status))
            
{
                
throw new MembershipPasswordException(GetExceptionText(status));
            }


            
throw new ProviderException(this.GetExceptionText(status));
        }


        
/// <summary>
        
/// 清除用户的锁定状态,以便可以验证该成员资格用户
        
/// </summary>
        
/// <param name="username"></param>
        
/// <returns></returns>

        public override bool UnlockUser(string username)
        
{
            SecUtility.CheckParameter(
ref username, truetruetrue255"username");

            
int status = ServiceLocator.UserService.UnlockUser(this._applicationName, username);

            
if (status == 0)
            
{
                
return true;
            }

            
else
            
{
                
return false;
            }

        }


        
/// <summary>
        
/// 更新成员资格数据库中用户的信息
        
/// </summary>
        
/// <param name="user"></param>

        public override void UpdateUser(MembershipUser user)
        
{
            
if (user == null)
            
{
                
throw new ArgumentNullException("user.");
            }


            
string email = user.Email;
            SecUtility.CheckParameter(
ref email, this._requiresUniqueEmail, this._requiresUniqueEmail, false255"email");
            user.Email 
= email;

            
int status = ServiceLocator.UserService.UpdateUser(this._applicationName, user.UserName, user.Email,
                user.Comment, user.IsApproved, user.LastLoginDate.ToUniversalTime(), user.LastActivityDate.ToUniversalTime(),
                
this._requiresUniqueEmail);

            
if (status != 0)
            
{
                
throw new ProviderException(GetExceptionText(status));
            }

        }


        
/// <summary>
        
/// 验证成员资格数据库中是否存在指定的用户名和密码
        
/// </summary>
        
/// <param name="username"></param>
        
/// <param name="password"></param>
        
/// <returns></returns>

        public override bool ValidateUser(string username, string password)
        
{
            
if ((SecUtility.ValidateParameter(ref username, truetruetrue255&&
                SecUtility.ValidateParameter(
ref password, truetruefalse128)) &&
                CheckPassword(username, password, 
truetrue))
            
{
                
return true;
            }

            
else
            
{
                
return false;
            }

        }


        
#endregion 方法

        
private bool IsStatusDueToBadPassword(int status)
        
{
            
if ((status >= 2&& (status <= 6))
            
{
                
return true;
            }

            
return (status == 99);
        }


        
private string GenerateSalt()
        
{
            
byte[] buffer = new byte[16];
            
new RNGCryptoServiceProvider().GetBytes(buffer);
            
return Convert.ToBase64String(buffer);
        }


        
private DateTime RoundToSeconds(DateTime dt)
        
{
            
return new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, dt.Second);
        }


        
private string GetEncodedPasswordAnswer(string username, string passwordAnswer)
        
{
            
if (passwordAnswer != null)
            
{
                passwordAnswer 
= passwordAnswer.Trim();
            }


            
if (!String.IsNullOrEmpty(passwordAnswer))
            
{
                
int status;
                
string password;
                MembershipPasswordFormat passwordFormat;
                
string salt;
                
int failedPasswordAttemptCount;
                
int failedPasswordAnswerAttemptCount;
                
bool isApproved;
                DateTime lastLoginDate;
                DateTime lastActivityDate;

                GetPasswordWithFormat(
this._applicationName, username, falseout status, out password,
                    
out passwordFormat, out salt, out failedPasswordAttemptCount, out failedPasswordAnswerAttemptCount,
                    
out isApproved, out lastLoginDate, out lastActivityDate);

                
if (status != 0)
                
{
                    
throw new ProviderException(GetExceptionText(status));
                }


                
return EncodePassword(passwordAnswer.ToLower(CultureInfo.InvariantCulture), passwordFormat, salt);
            }


            
return passwordAnswer;
        }


        
private string GeneratePassword()
        
{
            
return Membership.GeneratePassword((this._minRequiredPasswordLength < 14? 14 : this._minRequiredPasswordLength,
                
this._minRequiredNonAlphanumericCharacters);
        }



        
private string EncodePassword(string pass, MembershipPasswordFormat passwordFormat, string salt)
        
{
            
if (passwordFormat == MembershipPasswordFormat.Clear)
            
{
                
return pass;
            }


            
byte[] bIn = Encoding.Unicode.GetBytes(pass);
            
byte[] bSalt = Convert.FromBase64String(salt);
            
byte[] bAll = new byte[bSalt.Length + bIn.Length];
            
byte[] bRet = null;

            Buffer.BlockCopy(bSalt, 
0, bAll, 0, bSalt.Length);
            Buffer.BlockCopy(bIn, 
0, bAll, bSalt.Length, bIn.Length);
            
if (passwordFormat == MembershipPasswordFormat.Hashed)
            
{
                HashAlgorithm s 
= HashAlgorithm.Create(Membership.HashAlgorithmType);

                
if (s == null)
                
{
                    
throw new ProviderException("Could not create a hash algorithm");
                }

                bRet 
= s.ComputeHash(bAll);
            }

            
else
            
{
                bRet 
= base.EncryptPassword(bAll);
            }


            
return Convert.ToBase64String(bRet);
        }


        
private string UnEncodePassword(string pass, MembershipPasswordFormat passwordFormat)
        
{
            
switch (passwordFormat)
            
{
                
case MembershipPasswordFormat.Clear:
                    
return pass;

                
case MembershipPasswordFormat.Hashed:
                    
throw new ProviderException("Provider can not decode hashed password");
            }


            
byte[] buffer = this.DecryptPassword(Convert.FromBase64String(pass));

            
if (buffer == null)
            
{
                
return null;
            }


            
return Encoding.Unicode.GetString(buffer, 16, buffer.Length - 16);
        }


        
private bool CheckPassword(string username, string password, bool updateLastLoginActivityDate, bool failIfNotApproved)
        
{
            
string salt;
            MembershipPasswordFormat passwordFormat;
            
return CheckPassword(username, password, updateLastLoginActivityDate, failIfNotApproved,
                
out salt, out passwordFormat);
        }


        
private bool CheckPassword(string username, string password, bool updateLastLoginActivityDate, bool failIfNotApproved,
            
out string salt, out MembershipPasswordFormat passwordFormat)
        
{
            
int status;
            
string pass;
            
int failedPasswordAttemptCount;
            
int failedPasswordAnswerAttemptCount;
            
bool isApproved;
            DateTime lastLoginDate;
            DateTime lastActivityDate;


            GetPasswordWithFormat(
this._applicationName, username, updateLastLoginActivityDate, out status,
                
out pass, out passwordFormat, out salt, out failedPasswordAttemptCount,
                
out failedPasswordAnswerAttemptCount, out isApproved, out lastLoginDate, out  lastActivityDate);

            
if (status != 0)
            
{
                
return false;
            }

            
if (!isApproved && failIfNotApproved)
            
{
                
return false;
            }


            password 
= EncodePassword(password, passwordFormat, salt);

            
bool isPasswordCorrect = password.Equals(pass);

            
if ((isPasswordCorrect && (failedPasswordAttemptCount == 0)) && (failedPasswordAnswerAttemptCount == 0))
            
{
                
return true;
            }


            ServiceLocator.UserService.UpdateUserInfo(
this._applicationName, username, isPasswordCorrect,
                
this._passwordAttemptWindow, this._maxInvalidPasswordAttempts,
                updateLastLoginActivityDate, DateTime.UtcNow);

            
return isPasswordCorrect;

        }


        
private string GetExceptionText(int status)
        
{
            
string errText;
            
switch (status)
            
{
                
case 0:
                    
return String.Empty;

                
case 1:
                    errText 
= "Membership user not found.";
                    
break;

                
case 2:
                    errText 
= "Membership wrong password.";
                    
break;

                
case 3:
                    errText 
= "Membership wrong answer.";
                    
break;

                
case 4:
                    errText 
= "Membership invalid password.";
                    
break;

                
case 5:
                    errText 
= "Membership invalid question.";
                    
break;

                
case 6:
                    errText 
= "Membership invalid answer.";
                    
break;

                
case 7:
                    errText 
= "Membership invalid email.";
                    
break;

                
case 99:
                    errText 
= "Membership account lock out.";
                    
break;

                
default:
                    errText 
= "Provider error.";
                    
break;
            }

            
return errText;
        }


        
private int CreateUser(string applicationName, string username, string password, string passwordSalt,
            
string email, string passwordQuestion, string passwordAnswer, bool isApproved, bool uniqueEmail,
            MembershipPasswordFormat passwordFormat, DateTime currentTimeUtc, 
out int userID)
        
{
            userID 
= -1;


            
if (ServiceLocator.UserService.GetUserByName(applicationName, username) != null)
            
{
                
return 6//MembershipCreateStatus.DuplicateUserName
            }


            
if (uniqueEmail && ServiceLocator.UserService.GetUsersByEmail(applicationName, email).Count > 0)
            
{
                
return 7//MembershipCreateStatus.DuplicateEmail
            }


            User user 
= new User();
            user.Username 
= username;
            user.Email 
= email;
            user.Password 
= password;
            user.PasswordFormat 
= passwordFormat;
            user.PasswordSalt 
= passwordSalt;
            user.PasswordQuestion 
= passwordQuestion;
            user.PasswordAnswer 
= passwordAnswer;
            user.IsAnonymous 
= false;
            user.IsApproved 
= isApproved;
            user.IsLockedOut 
= false;
            user.CreateDate 
= currentTimeUtc;
            user.LastActivityDate 
= currentTimeUtc;
            user.LastLoginDate 
= currentTimeUtc;
            user.LastPasswordChangedDate 
= currentTimeUtc;
            user.LastLockoutDate 
= new DateTime(175411);
            user.FailedPasswordAttemptCount 
= 0;
            user.FailedPasswordAttemptWindowStart 
= new DateTime(175411);
            user.FailedPasswordAnswerAttemptCount 
= 0;
            user.FailedPasswordAnswerAttemptWindowStart 
= new DateTime(175411);
            user.Application 
= ServiceLocator.ApplicationService.GetApplication(applicationName);

            ServiceLocator.UserService.CreateUser(user);

            
if (user.ID > 0)
            
{
                userID 
= user.ID;
                
return 0;//MembershipCreateStatus.Success
            }

            
else
            
{
                
return 11;//MembershipCreateStatus.ProviderError
            }

        }



        
private void GetPasswordWithFormat(string applicationName, string username, bool updateLastLoginActivityDate, out int status,
             
out string password, out MembershipPasswordFormat passwordFormat, out string passwordSalt,
             
out int failedPasswordAttemptCount, out int failedPasswordAnswerAttemptCount, out bool isApproved,
             
out DateTime lastLoginDate, out DateTime lastActivityDate)
        
{
            User user 
= ServiceLocator.UserService.GetUserByName(applicationName, username);

            
if (user != null)
            
{
                
if (updateLastLoginActivityDate && user.IsApproved)
                
{
                    user.LastActivityDate 
= DateTime.UtcNow;
                    user.LastLoginDate 
= DateTime.UtcNow;

                    ServiceLocator.UserService.UpdateUser(user);
                }


                password 
= user.Password;
                passwordFormat 
= user.PasswordFormat;
                passwordSalt 
= user.PasswordSalt;
                failedPasswordAttemptCount 
= user.FailedPasswordAttemptCount;
                failedPasswordAnswerAttemptCount 
= user.FailedPasswordAnswerAttemptCount;
                isApproved 
= user.IsApproved;
                lastLoginDate 
= user.LastLoginDate;
                lastActivityDate 
= user.LastActivityDate;

                status 
= 0;
            }

            
else
            
{
                password 
= null;
                passwordFormat 
= MembershipPasswordFormat.Clear;
                passwordSalt 
= null;
                failedPasswordAttemptCount 
= 0;
                failedPasswordAnswerAttemptCount 
= 0;
                isApproved 
= false;
                lastLoginDate 
= DateTime.UtcNow;
                lastActivityDate 
= DateTime.UtcNow;

                status 
= 1;
            }

        }

    }
}

posted on 2008-05-17 20:32  guushuuse  阅读(727)  评论(1编辑  收藏  举报