2014-08-13 10:39:27 +01:00
//
// System.Web.Security.SqlMembershipProvider
//
// Authors:
// Ben Maurer (bmaurer@users.sourceforge.net)
// Lluis Sanchez Gual (lluis@novell.com)
// Chris Toshok (toshok@ximian.com)
//
// (C) 2003 Ben Maurer
// Copyright (c) 2005,2006 Novell, Inc (http://www.novell.com)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System.Collections ;
using System.Collections.Specialized ;
using System.Configuration ;
using System.Configuration.Provider ;
using System.Data ;
using System.Data.Common ;
using System.Text ;
using System.Web.Configuration ;
using System.Security.Cryptography ;
namespace System.Web.Security {
public class SqlMembershipProvider : MembershipProvider
{
bool enablePasswordReset ;
bool enablePasswordRetrieval ;
int maxInvalidPasswordAttempts ;
MembershipPasswordFormat passwordFormat ;
bool requiresQuestionAndAnswer ;
bool requiresUniqueEmail ;
int minRequiredNonAlphanumericCharacters ;
int minRequiredPasswordLength ;
int passwordAttemptWindow ;
string passwordStrengthRegularExpression ;
TimeSpan userIsOnlineTimeWindow ;
ConnectionStringSettings connectionString ;
DbProviderFactory factory ;
string applicationName ;
bool schemaIsOk = false ;
DbConnection CreateConnection ( )
{
if ( ! schemaIsOk & & ! ( schemaIsOk = AspNetDBSchemaChecker . CheckMembershipSchemaVersion ( factory , connectionString . ConnectionString , "membership" , "1" ) ) )
throw new ProviderException ( "Incorrect ASP.NET DB Schema Version." ) ;
DbConnection connection ;
if ( connectionString = = null )
throw new ProviderException ( "Connection string for the SQL Membership Provider has not been provided." ) ;
try {
connection = factory . CreateConnection ( ) ;
connection . ConnectionString = connectionString . ConnectionString ;
connection . Open ( ) ;
} catch ( Exception ex ) {
throw new ProviderException ( "Unable to open SQL connection for the SQL Membership Provider." ,
ex ) ;
}
return connection ;
}
DbParameter AddParameter ( DbCommand command , string parameterName , object parameterValue )
{
return AddParameter ( command , parameterName , ParameterDirection . Input , parameterValue ) ;
}
DbParameter AddParameter ( DbCommand command , string parameterName , ParameterDirection direction , object parameterValue )
{
DbParameter dbp = command . CreateParameter ( ) ;
dbp . ParameterName = parameterName ;
dbp . Value = parameterValue ;
dbp . Direction = direction ;
command . Parameters . Add ( dbp ) ;
return dbp ;
}
DbParameter AddParameter ( DbCommand command , string parameterName , ParameterDirection direction , DbType type , object parameterValue )
{
DbParameter dbp = command . CreateParameter ( ) ;
dbp . ParameterName = parameterName ;
dbp . Value = parameterValue ;
dbp . Direction = direction ;
dbp . DbType = type ;
command . Parameters . Add ( dbp ) ;
return dbp ;
}
static int GetReturnValue ( DbParameter returnValue )
{
object value = returnValue . Value ;
return value is int ? ( int ) value : - 1 ;
}
void CheckParam ( string pName , string p , int length )
{
if ( p = = null )
throw new ArgumentNullException ( pName ) ;
if ( p . Length = = 0 | | p . Length > length | | p . IndexOf ( ',' ) ! = - 1 )
throw new ArgumentException ( String . Format ( "invalid format for {0}" , pName ) ) ;
}
2017-06-07 13:16:24 +00:00
public override bool ChangePassword ( string username , string oldPassword , string newPassword )
2014-08-13 10:39:27 +01:00
{
if ( username ! = null ) username = username . Trim ( ) ;
2017-06-07 13:16:24 +00:00
if ( oldPassword ! = null ) oldPassword = oldPassword . Trim ( ) ;
if ( newPassword ! = null ) newPassword = newPassword . Trim ( ) ;
2014-08-13 10:39:27 +01:00
CheckParam ( "username" , username , 256 ) ;
2017-06-07 13:16:24 +00:00
CheckParam ( "oldPassword" , oldPassword , 128 ) ;
CheckParam ( "newPassword" , newPassword , 128 ) ;
2014-08-13 10:39:27 +01:00
2017-06-07 13:16:24 +00:00
if ( ! CheckPassword ( newPassword ) )
2014-08-13 10:39:27 +01:00
throw new ArgumentException ( string . Format (
"New Password invalid. New Password length minimum: {0}. Non-alphanumeric characters required: {1}." ,
MinRequiredPasswordLength ,
MinRequiredNonAlphanumericCharacters ) ) ;
using ( DbConnection connection = CreateConnection ( ) ) {
2017-06-07 13:16:24 +00:00
PasswordInfo pi = ValidateUsingPassword ( username , oldPassword ) ;
2014-08-13 10:39:27 +01:00
if ( pi ! = null ) {
2017-06-07 13:16:24 +00:00
EmitValidatingPassword ( username , newPassword , false ) ;
string db_password = EncodePassword ( newPassword , pi . PasswordFormat , pi . PasswordSalt ) ;
2014-08-13 10:39:27 +01:00
DbCommand command = factory . CreateCommand ( ) ;
command . Connection = connection ;
command . CommandText = @"aspnet_Membership_SetPassword" ;
command . CommandType = CommandType . StoredProcedure ;
AddParameter ( command , "@ApplicationName" , ApplicationName ) ;
AddParameter ( command , "@UserName" , username ) ;
AddParameter ( command , "@NewPassword" , db_password ) ;
AddParameter ( command , "@PasswordFormat" , ( int ) pi . PasswordFormat ) ;
AddParameter ( command , "@PasswordSalt" , pi . PasswordSalt ) ;
AddParameter ( command , "@CurrentTimeUtc" , DateTime . UtcNow ) ;
DbParameter returnValue = AddParameter ( command , "@ReturnVal" , ParameterDirection . ReturnValue , DbType . Int32 , null ) ;
command . ExecuteNonQuery ( ) ;
if ( GetReturnValue ( returnValue ) ! = 0 )
return false ;
return true ;
}
return false ;
}
}
2017-06-07 13:16:24 +00:00
public override bool ChangePasswordQuestionAndAnswer ( string username , string password , string newPasswordQuestion , string newPasswordAnswer )
2014-08-13 10:39:27 +01:00
{
if ( username ! = null ) username = username . Trim ( ) ;
2017-06-07 13:16:24 +00:00
if ( newPasswordQuestion ! = null ) newPasswordQuestion = newPasswordQuestion . Trim ( ) ;
if ( newPasswordAnswer ! = null ) newPasswordAnswer = newPasswordAnswer . Trim ( ) ;
2014-08-13 10:39:27 +01:00
CheckParam ( "username" , username , 256 ) ;
if ( RequiresQuestionAndAnswer )
2017-06-07 13:16:24 +00:00
CheckParam ( "newPasswordQuestion" , newPasswordQuestion , 128 ) ;
2014-08-13 10:39:27 +01:00
if ( RequiresQuestionAndAnswer )
2017-06-07 13:16:24 +00:00
CheckParam ( "newPasswordAnswer" , newPasswordAnswer , 128 ) ;
2014-08-13 10:39:27 +01:00
using ( DbConnection connection = CreateConnection ( ) ) {
PasswordInfo pi = ValidateUsingPassword ( username , password ) ;
if ( pi ! = null ) {
2017-06-07 13:16:24 +00:00
string db_passwordAnswer = EncodePassword ( newPasswordAnswer , pi . PasswordFormat , pi . PasswordSalt ) ;
2014-08-13 10:39:27 +01:00
DbCommand command = factory . CreateCommand ( ) ;
command . Connection = connection ;
command . CommandType = CommandType . StoredProcedure ;
command . CommandText = @"aspnet_Membership_ChangePasswordQuestionAndAnswer" ;
AddParameter ( command , "@ApplicationName" , ApplicationName ) ;
AddParameter ( command , "@UserName" , username ) ;
2017-06-07 13:16:24 +00:00
AddParameter ( command , "@NewPasswordQuestion" , newPasswordQuestion ) ;
2014-08-13 10:39:27 +01:00
AddParameter ( command , "@NewPasswordAnswer" , db_passwordAnswer ) ;
DbParameter returnValue = AddParameter ( command , "@ReturnVal" , ParameterDirection . ReturnValue , DbType . Int32 , null ) ;
command . ExecuteNonQuery ( ) ;
if ( GetReturnValue ( returnValue ) ! = 0 )
return false ;
return true ;
}
return false ;
}
}
public override MembershipUser CreateUser ( string username ,
string password ,
string email ,
2017-06-07 13:16:24 +00:00
string passwordQuestion ,
string passwordAnswer ,
2014-08-13 10:39:27 +01:00
bool isApproved ,
object providerUserKey ,
out MembershipCreateStatus status )
{
if ( username ! = null ) username = username . Trim ( ) ;
if ( password ! = null ) password = password . Trim ( ) ;
if ( email ! = null ) email = email . Trim ( ) ;
2017-06-07 13:16:24 +00:00
if ( passwordQuestion ! = null ) passwordQuestion = passwordQuestion . Trim ( ) ;
if ( passwordAnswer ! = null ) passwordAnswer = passwordAnswer . Trim ( ) ;
2014-08-13 10:39:27 +01:00
/* some initial validation */
if ( username = = null | | username . Length = = 0 | | username . Length > 256 | | username . IndexOf ( ',' ) ! = - 1 ) {
status = MembershipCreateStatus . InvalidUserName ;
return null ;
}
if ( password = = null | | password . Length = = 0 | | password . Length > 128 ) {
status = MembershipCreateStatus . InvalidPassword ;
return null ;
}
if ( ! CheckPassword ( password ) ) {
status = MembershipCreateStatus . InvalidPassword ;
return null ;
}
EmitValidatingPassword ( username , password , true ) ;
if ( RequiresUniqueEmail & & ( email = = null | | email . Length = = 0 ) ) {
status = MembershipCreateStatus . InvalidEmail ;
return null ;
}
if ( RequiresQuestionAndAnswer & &
2017-06-07 13:16:24 +00:00
( passwordQuestion = = null | |
passwordQuestion . Length = = 0 | | passwordQuestion . Length > 256 ) ) {
2014-08-13 10:39:27 +01:00
status = MembershipCreateStatus . InvalidQuestion ;
return null ;
}
if ( RequiresQuestionAndAnswer & &
2017-06-07 13:16:24 +00:00
( passwordAnswer = = null | |
passwordAnswer . Length = = 0 | | passwordAnswer . Length > 128 ) ) {
2014-08-13 10:39:27 +01:00
status = MembershipCreateStatus . InvalidAnswer ;
return null ;
}
if ( providerUserKey ! = null & & ! ( providerUserKey is Guid ) ) {
status = MembershipCreateStatus . InvalidProviderUserKey ;
return null ;
}
if ( providerUserKey = = null )
providerUserKey = Guid . NewGuid ( ) ;
/ * encode our password / answer using the
* "passwordFormat" configuration option * /
string passwordSalt = "" ;
RandomNumberGenerator rng = RandomNumberGenerator . Create ( ) ;
byte [ ] salt = new byte [ MembershipHelper . SALT_BYTES ] ;
rng . GetBytes ( salt ) ;
passwordSalt = Convert . ToBase64String ( salt ) ;
password = EncodePassword ( password , PasswordFormat , passwordSalt ) ;
if ( RequiresQuestionAndAnswer )
2017-06-07 13:16:24 +00:00
passwordAnswer = EncodePassword ( passwordAnswer , PasswordFormat , passwordSalt ) ;
2014-08-13 10:39:27 +01:00
/ * make sure the hashed / encrypted password and
* answer are still under 128 characters . * /
if ( password . Length > 128 ) {
status = MembershipCreateStatus . InvalidPassword ;
return null ;
}
if ( RequiresQuestionAndAnswer ) {
2017-06-07 13:16:24 +00:00
if ( passwordAnswer . Length > 128 ) {
2014-08-13 10:39:27 +01:00
status = MembershipCreateStatus . InvalidAnswer ;
return null ;
}
}
status = MembershipCreateStatus . Success ;
using ( DbConnection connection = CreateConnection ( ) ) {
try {
DbCommand command = factory . CreateCommand ( ) ;
command . Connection = connection ;
command . CommandText = @"aspnet_Membership_CreateUser" ;
command . CommandType = CommandType . StoredProcedure ;
DateTime Now = DateTime . UtcNow ;
AddParameter ( command , "@ApplicationName" , ApplicationName ) ;
AddParameter ( command , "@UserName" , username ) ;
AddParameter ( command , "@Password" , password ) ;
AddParameter ( command , "@PasswordSalt" , passwordSalt ) ;
AddParameter ( command , "@Email" , email ) ;
2017-06-07 13:16:24 +00:00
AddParameter ( command , "@PasswordQuestion" , passwordQuestion ) ;
AddParameter ( command , "@PasswordAnswer" , passwordAnswer ) ;
2014-08-13 10:39:27 +01:00
AddParameter ( command , "@IsApproved" , isApproved ) ;
AddParameter ( command , "@CurrentTimeUtc" , Now ) ;
AddParameter ( command , "@CreateDate" , Now ) ;
AddParameter ( command , "@UniqueEmail" , RequiresUniqueEmail ) ;
AddParameter ( command , "@PasswordFormat" , ( int ) PasswordFormat ) ;
AddParameter ( command , "@UserId" , ParameterDirection . InputOutput , providerUserKey ) ;
DbParameter returnValue = AddParameter ( command , "@ReturnVal" , ParameterDirection . ReturnValue , DbType . Int32 , null ) ;
command . ExecuteNonQuery ( ) ;
int st = GetReturnValue ( returnValue ) ;
if ( st = = 0 )
return GetUser ( username , false ) ;
else if ( st = = 6 )
status = MembershipCreateStatus . DuplicateUserName ;
else if ( st = = 7 )
status = MembershipCreateStatus . DuplicateEmail ;
else if ( st = = 10 )
status = MembershipCreateStatus . DuplicateProviderUserKey ;
else
status = MembershipCreateStatus . ProviderError ;
return null ;
}
catch ( Exception ) {
status = MembershipCreateStatus . ProviderError ;
return null ;
}
}
}
bool CheckPassword ( string password )
{
if ( password . Length < MinRequiredPasswordLength )
return false ;
if ( MinRequiredNonAlphanumericCharacters > 0 ) {
int nonAlphanumeric = 0 ;
for ( int i = 0 ; i < password . Length ; i + + ) {
if ( ! Char . IsLetterOrDigit ( password [ i ] ) )
nonAlphanumeric + + ;
}
return nonAlphanumeric > = MinRequiredNonAlphanumericCharacters ;
}
return true ;
}
public override bool DeleteUser ( string username , bool deleteAllRelatedData )
{
CheckParam ( "username" , username , 256 ) ;
DeleteUserTableMask deleteBitmask = DeleteUserTableMask . MembershipUsers ;
if ( deleteAllRelatedData )
deleteBitmask | =
DeleteUserTableMask . Profiles |
DeleteUserTableMask . UsersInRoles |
DeleteUserTableMask . WebPartStateUser ;
using ( DbConnection connection = CreateConnection ( ) ) {
DbCommand command = factory . CreateCommand ( ) ;
command . Connection = connection ;
command . CommandText = @"aspnet_Users_DeleteUser" ;
command . CommandType = CommandType . StoredProcedure ;
AddParameter ( command , "@ApplicationName" , ApplicationName ) ;
AddParameter ( command , "@UserName" , username ) ;
AddParameter ( command , "@TablesToDeleteFrom" , ( int ) deleteBitmask ) ;
AddParameter ( command , "@NumTablesDeletedFrom" , ParameterDirection . Output , 0 ) ;
DbParameter returnValue = AddParameter ( command , "@ReturnVal" , ParameterDirection . ReturnValue , DbType . Int32 , null ) ;
command . ExecuteNonQuery ( ) ;
if ( ( ( int ) command . Parameters [ "@NumTablesDeletedFrom" ] . Value ) = = 0 )
return false ;
if ( GetReturnValue ( returnValue ) = = 0 )
return true ;
return false ;
}
}
public virtual string GeneratePassword ( )
{
return Membership . GeneratePassword ( MinRequiredPasswordLength , MinRequiredNonAlphanumericCharacters ) ;
}
public override MembershipUserCollection FindUsersByEmail ( string emailToMatch , int pageIndex , int pageSize , out int totalRecords )
{
CheckParam ( "emailToMatch" , emailToMatch , 256 ) ;
if ( pageIndex < 0 )
throw new ArgumentException ( "pageIndex must be >= 0" ) ;
if ( pageSize < 0 )
throw new ArgumentException ( "pageSize must be >= 0" ) ;
if ( pageIndex * pageSize + pageSize - 1 > Int32 . MaxValue )
throw new ArgumentException ( "pageIndex and pageSize are too large" ) ;
using ( DbConnection connection = CreateConnection ( ) ) {
DbCommand command = factory . CreateCommand ( ) ;
command . Connection = connection ;
command . CommandText = @"aspnet_Membership_FindUsersByEmail" ;
command . CommandType = CommandType . StoredProcedure ;
AddParameter ( command , "@PageIndex" , pageIndex ) ;
AddParameter ( command , "@PageSize" , pageSize ) ;
AddParameter ( command , "@EmailToMatch" , emailToMatch ) ;
AddParameter ( command , "@ApplicationName" , ApplicationName ) ;
// return value
AddParameter ( command , "@ReturnValue" , ParameterDirection . ReturnValue , null ) ;
MembershipUserCollection c = BuildMembershipUserCollection ( command , pageIndex , pageSize , out totalRecords ) ;
return c ;
}
}
2017-06-07 13:16:24 +00:00
public override MembershipUserCollection FindUsersByName ( string usernameToMatch , int pageIndex , int pageSize , out int totalRecords )
2014-08-13 10:39:27 +01:00
{
2017-06-07 13:16:24 +00:00
CheckParam ( "usernameToMatch" , usernameToMatch , 256 ) ;
2014-08-13 10:39:27 +01:00
if ( pageIndex < 0 )
throw new ArgumentException ( "pageIndex must be >= 0" ) ;
if ( pageSize < 0 )
throw new ArgumentException ( "pageSize must be >= 0" ) ;
if ( pageIndex * pageSize + pageSize - 1 > Int32 . MaxValue )
throw new ArgumentException ( "pageIndex and pageSize are too large" ) ;
using ( DbConnection connection = CreateConnection ( ) ) {
DbCommand command = factory . CreateCommand ( ) ;
command . Connection = connection ;
command . CommandText = @"aspnet_Membership_FindUsersByName" ;
command . CommandType = CommandType . StoredProcedure ;
AddParameter ( command , "@PageIndex" , pageIndex ) ;
AddParameter ( command , "@PageSize" , pageSize ) ;
2017-06-07 13:16:24 +00:00
AddParameter ( command , "@UserNameToMatch" , usernameToMatch ) ;
2014-08-13 10:39:27 +01:00
AddParameter ( command , "@ApplicationName" , ApplicationName ) ;
// return value
AddParameter ( command , "@ReturnValue" , ParameterDirection . ReturnValue , null ) ;
MembershipUserCollection c = BuildMembershipUserCollection ( command , pageIndex , pageSize , out totalRecords ) ;
return c ;
}
}
public override MembershipUserCollection GetAllUsers ( int pageIndex , int pageSize , out int totalRecords )
{
if ( pageIndex < 0 )
throw new ArgumentException ( "pageIndex must be >= 0" ) ;
if ( pageSize < 0 )
throw new ArgumentException ( "pageSize must be >= 0" ) ;
if ( pageIndex * pageSize + pageSize - 1 > Int32 . MaxValue )
throw new ArgumentException ( "pageIndex and pageSize are too large" ) ;
using ( DbConnection connection = CreateConnection ( ) ) {
DbCommand command = factory . CreateCommand ( ) ;
command . Connection = connection ;
command . CommandText = @"aspnet_Membership_GetAllUsers" ;
command . CommandType = CommandType . StoredProcedure ;
AddParameter ( command , "@ApplicationName" , ApplicationName ) ;
AddParameter ( command , "@PageIndex" , pageIndex ) ;
AddParameter ( command , "@PageSize" , pageSize ) ;
// return value
AddParameter ( command , "@ReturnValue" , ParameterDirection . ReturnValue , null ) ;
MembershipUserCollection c = BuildMembershipUserCollection ( command , pageIndex , pageSize , out totalRecords ) ;
return c ;
}
}
MembershipUserCollection BuildMembershipUserCollection ( DbCommand command , int pageIndex , int pageSize , out int totalRecords )
{
DbDataReader reader = null ;
try {
MembershipUserCollection users = new MembershipUserCollection ( ) ;
reader = command . ExecuteReader ( ) ;
while ( reader . Read ( ) )
users . Add ( GetUserFromReader ( reader , null , null ) ) ;
totalRecords = Convert . ToInt32 ( command . Parameters [ "@ReturnValue" ] . Value ) ;
return users ;
} catch ( Exception ) {
totalRecords = 0 ;
return null ; /* should we let the exception through? */
}
finally {
if ( reader ! = null )
reader . Close ( ) ;
}
}
public override int GetNumberOfUsersOnline ( )
{
using ( DbConnection connection = CreateConnection ( ) ) {
DateTime now = DateTime . UtcNow ;
DbCommand command = factory . CreateCommand ( ) ;
command . Connection = connection ;
command . CommandText = @"aspnet_Membership_GetNumberOfUsersOnline" ;
command . CommandType = CommandType . StoredProcedure ;
AddParameter ( command , "@CurrentTimeUtc" , now . ToString ( ) ) ;
AddParameter ( command , "@ApplicationName" , ApplicationName ) ;
AddParameter ( command , "@MinutesSinceLastInActive" , userIsOnlineTimeWindow . Minutes ) ;
DbParameter returnValue = AddParameter ( command , "@ReturnVal" , ParameterDirection . ReturnValue , DbType . Int32 , null ) ;
command . ExecuteScalar ( ) ;
return GetReturnValue ( returnValue ) ;
}
}
2017-06-07 13:16:24 +00:00
public override string GetPassword ( string username , string passwordAnswer )
2014-08-13 10:39:27 +01:00
{
if ( ! EnablePasswordRetrieval )
throw new NotSupportedException ( "this provider has not been configured to allow the retrieval of passwords" ) ;
CheckParam ( "username" , username , 256 ) ;
if ( RequiresQuestionAndAnswer )
2017-06-07 13:16:24 +00:00
CheckParam ( "passwordAnswer" , passwordAnswer , 128 ) ;
2014-08-13 10:39:27 +01:00
PasswordInfo pi = GetPasswordInfo ( username ) ;
if ( pi = = null )
throw new ProviderException ( "An error occurred while retrieving the password from the database" ) ;
2017-06-07 13:16:24 +00:00
string user_answer = EncodePassword ( passwordAnswer , pi . PasswordFormat , pi . PasswordSalt ) ;
2014-08-13 10:39:27 +01:00
string password = null ;
using ( DbConnection connection = CreateConnection ( ) ) {
DbCommand command = factory . CreateCommand ( ) ;
command . Connection = connection ;
command . CommandText = @"aspnet_Membership_GetPassword" ;
command . CommandType = CommandType . StoredProcedure ;
AddParameter ( command , "@ApplicationName" , ApplicationName ) ;
AddParameter ( command , "@UserName" , username ) ;
AddParameter ( command , "@MaxInvalidPasswordAttempts" , MaxInvalidPasswordAttempts ) ;
AddParameter ( command , "@PasswordAttemptWindow" , PasswordAttemptWindow ) ;
AddParameter ( command , "@CurrentTimeUtc" , DateTime . UtcNow ) ;
AddParameter ( command , "@PasswordAnswer" , user_answer ) ;
DbParameter retValue = AddParameter ( command , "@ReturnVal" , ParameterDirection . ReturnValue , DbType . Int32 , null ) ;
DbDataReader reader = command . ExecuteReader ( ) ;
int returnValue = GetReturnValue ( retValue ) ;
if ( returnValue = = 3 )
throw new MembershipPasswordException ( "Password Answer is invalid" ) ;
if ( returnValue = = 99 )
throw new MembershipPasswordException ( "The user account is currently locked out" ) ;
if ( reader . Read ( ) ) {
password = reader . GetString ( 0 ) ;
reader . Close ( ) ;
}
if ( pi . PasswordFormat = = MembershipPasswordFormat . Clear )
return password ;
else if ( pi . PasswordFormat = = MembershipPasswordFormat . Encrypted )
return DecodePassword ( password , pi . PasswordFormat ) ;
return password ;
}
}
MembershipUser GetUserFromReader ( DbDataReader reader , string username , object userId )
{
int i = 0 ;
if ( username = = null )
i = 1 ;
if ( userId ! = null )
username = reader . GetString ( 8 ) ;
return new MembershipUser ( this . Name , /* XXX is this right? */
( username = = null ? reader . GetString ( 0 ) : username ) , /* name */
( userId = = null ? reader . GetGuid ( 8 + i ) : userId ) , /* providerUserKey */
reader . IsDBNull ( 0 + i ) ? null : reader . GetString ( 0 + i ) , /* email */
reader . IsDBNull ( 1 + i ) ? null : reader . GetString ( 1 + i ) , /* passwordQuestion */
reader . IsDBNull ( 2 + i ) ? null : reader . GetString ( 2 + i ) , /* comment */
reader . GetBoolean ( 3 + i ) , /* isApproved */
reader . GetBoolean ( 9 + i ) , /* isLockedOut */
reader . GetDateTime ( 4 + i ) . ToLocalTime ( ) , /* creationDate */
reader . GetDateTime ( 5 + i ) . ToLocalTime ( ) , /* lastLoginDate */
reader . GetDateTime ( 6 + i ) . ToLocalTime ( ) , /* lastActivityDate */
reader . GetDateTime ( 7 + i ) . ToLocalTime ( ) , /* lastPasswordChangedDate */
reader . GetDateTime ( 10 + i ) . ToLocalTime ( ) /* lastLockoutDate */ ) ;
}
MembershipUser BuildMembershipUser ( DbCommand query , string username , object userId )
{
try {
using ( DbConnection connection = CreateConnection ( ) ) {
query . Connection = connection ;
using ( DbDataReader reader = query . ExecuteReader ( ) ) {
if ( ! reader . Read ( ) )
return null ;
return GetUserFromReader ( reader , username , userId ) ;
}
}
} catch ( Exception ) {
return null ; /* should we let the exception through? */
}
finally {
query . Connection = null ;
}
}
public override MembershipUser GetUser ( string username , bool userIsOnline )
{
if ( username = = null )
throw new ArgumentNullException ( "username" ) ;
if ( username . Length = = 0 )
return null ;
CheckParam ( "username" , username , 256 ) ;
DbCommand command = factory . CreateCommand ( ) ;
command . CommandText = @"aspnet_Membership_GetUserByName" ;
command . CommandType = CommandType . StoredProcedure ;
AddParameter ( command , "@UserName" , username ) ;
AddParameter ( command , "@ApplicationName" , ApplicationName ) ;
AddParameter ( command , "@CurrentTimeUtc" , DateTime . Now ) ;
AddParameter ( command , "@UpdateLastActivity" , userIsOnline ) ;
MembershipUser u = BuildMembershipUser ( command , username , null ) ;
return u ;
}
public override MembershipUser GetUser ( object providerUserKey , bool userIsOnline )
{
DbCommand command = factory . CreateCommand ( ) ;
command . CommandText = @"aspnet_Membership_GetUserByUserId" ;
command . CommandType = CommandType . StoredProcedure ;
AddParameter ( command , "@UserId" , providerUserKey ) ;
AddParameter ( command , "@CurrentTimeUtc" , DateTime . Now ) ;
AddParameter ( command , "@UpdateLastActivity" , userIsOnline ) ;
MembershipUser u = BuildMembershipUser ( command , string . Empty , providerUserKey ) ;
return u ;
}
public override string GetUserNameByEmail ( string email )
{
CheckParam ( "email" , email , 256 ) ;
using ( DbConnection connection = CreateConnection ( ) ) {
DbCommand command = factory . CreateCommand ( ) ;
command . Connection = connection ;
command . CommandText = @"aspnet_Membership_GetUserByEmail" ;
command . CommandType = CommandType . StoredProcedure ;
AddParameter ( command , "@ApplicationName" , ApplicationName ) ;
AddParameter ( command , "@Email" , email ) ;
DbDataReader reader = command . ExecuteReader ( ) ;
string rv = null ;
if ( reader . Read ( ) )
rv = reader . GetString ( 0 ) ;
reader . Close ( ) ;
return rv ;
}
}
bool GetBoolConfigValue ( NameValueCollection config , string name , bool def )
{
bool rv = def ;
string val = config [ name ] ;
if ( val ! = null ) {
try { rv = Boolean . Parse ( val ) ; }
catch ( Exception e ) {
throw new ProviderException ( String . Format ( "{0} must be true or false" , name ) , e ) ;
}
}
return rv ;
}
int GetIntConfigValue ( NameValueCollection config , string name , int def )
{
int rv = def ;
string val = config [ name ] ;
if ( val ! = null ) {
try { rv = Int32 . Parse ( val ) ; }
catch ( Exception e ) {
throw new ProviderException ( String . Format ( "{0} must be an integer" , name ) , e ) ;
}
}
return rv ;
}
int GetEnumConfigValue ( NameValueCollection config , string name , Type enumType , int def )
{
int rv = def ;
string val = config [ name ] ;
if ( val ! = null ) {
try { rv = ( int ) Enum . Parse ( enumType , val ) ; }
catch ( Exception e ) {
throw new ProviderException ( String . Format ( "{0} must be one of the following values: {1}" , name , String . Join ( "," , Enum . GetNames ( enumType ) ) ) , e ) ;
}
}
return rv ;
}
string GetStringConfigValue ( NameValueCollection config , string name , string def )
{
string rv = def ;
string val = config [ name ] ;
if ( val ! = null )
rv = val ;
return rv ;
}
void EmitValidatingPassword ( string username , string password , bool isNewUser )
{
ValidatePasswordEventArgs args = new ValidatePasswordEventArgs ( username , password , isNewUser ) ;
OnValidatingPassword ( args ) ;
/* if we're canceled.. */
if ( args . Cancel ) {
if ( args . FailureInformation = = null )
throw new ProviderException ( "Password validation canceled" ) ;
else
throw args . FailureInformation ;
}
}
public override void Initialize ( string name , NameValueCollection config )
{
if ( config = = null )
throw new ArgumentNullException ( "config" ) ;
base . Initialize ( name , config ) ;
applicationName = GetStringConfigValue ( config , "applicationName" , "/" ) ;
enablePasswordReset = GetBoolConfigValue ( config , "enablePasswordReset" , true ) ;
enablePasswordRetrieval = GetBoolConfigValue ( config , "enablePasswordRetrieval" , false ) ;
requiresQuestionAndAnswer = GetBoolConfigValue ( config , "requiresQuestionAndAnswer" , true ) ;
requiresUniqueEmail = GetBoolConfigValue ( config , "requiresUniqueEmail" , false ) ;
passwordFormat = ( MembershipPasswordFormat ) GetEnumConfigValue ( config , "passwordFormat" , typeof ( MembershipPasswordFormat ) ,
( int ) MembershipPasswordFormat . Hashed ) ;
maxInvalidPasswordAttempts = GetIntConfigValue ( config , "maxInvalidPasswordAttempts" , 5 ) ;
minRequiredPasswordLength = GetIntConfigValue ( config , "minRequiredPasswordLength" , 7 ) ;
minRequiredNonAlphanumericCharacters = GetIntConfigValue ( config , "minRequiredNonalphanumericCharacters" , 1 ) ;
passwordAttemptWindow = GetIntConfigValue ( config , "passwordAttemptWindow" , 10 ) ;
passwordStrengthRegularExpression = GetStringConfigValue ( config , "passwordStrengthRegularExpression" , "" ) ;
MembershipSection section = ( MembershipSection ) WebConfigurationManager . GetSection ( "system.web/membership" ) ;
userIsOnlineTimeWindow = section . UserIsOnlineTimeWindow ;
/* we can't support password retrieval with hashed passwords */
if ( passwordFormat = = MembershipPasswordFormat . Hashed & & enablePasswordRetrieval )
throw new ProviderException ( "password retrieval cannot be used with hashed passwords" ) ;
string connectionStringName = config [ "connectionStringName" ] ;
if ( applicationName . Length > 256 )
throw new ProviderException ( "The ApplicationName attribute must be 256 characters long or less." ) ;
if ( connectionStringName = = null | | connectionStringName . Length = = 0 )
throw new ProviderException ( "The ConnectionStringName attribute must be present and non-zero length." ) ;
connectionString = WebConfigurationManager . ConnectionStrings [ connectionStringName ] ;
factory = connectionString = = null | | String . IsNullOrEmpty ( connectionString . ProviderName ) ?
System . Data . SqlClient . SqlClientFactory . Instance :
ProvidersHelper . GetDbProviderFactory ( connectionString . ProviderName ) ;
}
2017-06-07 13:16:24 +00:00
public override string ResetPassword ( string username , string passwordAnswer )
2014-08-13 10:39:27 +01:00
{
if ( ! EnablePasswordReset )
throw new NotSupportedException ( "this provider has not been configured to allow the resetting of passwords" ) ;
CheckParam ( "username" , username , 256 ) ;
if ( RequiresQuestionAndAnswer )
2017-06-07 13:16:24 +00:00
CheckParam ( "passwordAnswer" , passwordAnswer , 128 ) ;
2014-08-13 10:39:27 +01:00
using ( DbConnection connection = CreateConnection ( ) ) {
PasswordInfo pi = GetPasswordInfo ( username ) ;
if ( pi = = null )
throw new ProviderException ( username + "is not found in the membership database" ) ;
string newPassword = GeneratePassword ( ) ;
EmitValidatingPassword ( username , newPassword , false ) ;
string db_password = EncodePassword ( newPassword , pi . PasswordFormat , pi . PasswordSalt ) ;
2017-06-07 13:16:24 +00:00
string db_answer = EncodePassword ( passwordAnswer , pi . PasswordFormat , pi . PasswordSalt ) ;
2014-08-13 10:39:27 +01:00
DbCommand command = factory . CreateCommand ( ) ;
command . Connection = connection ;
command . CommandText = @"aspnet_Membership_ResetPassword" ;
command . CommandType = CommandType . StoredProcedure ;
AddParameter ( command , "@ApplicationName" , ApplicationName ) ;
AddParameter ( command , "@UserName" , username ) ;
AddParameter ( command , "@NewPassword" , db_password ) ;
AddParameter ( command , "@MaxInvalidPasswordAttempts" , MaxInvalidPasswordAttempts ) ;
AddParameter ( command , "@PasswordAttemptWindow" , PasswordAttemptWindow ) ;
AddParameter ( command , "@PasswordSalt" , pi . PasswordSalt ) ;
AddParameter ( command , "@CurrentTimeUtc" , DateTime . UtcNow ) ;
AddParameter ( command , "@PasswordFormat" , ( int ) pi . PasswordFormat ) ;
AddParameter ( command , "@PasswordAnswer" , db_answer ) ;
DbParameter retValue = AddParameter ( command , "@ReturnVal" , ParameterDirection . ReturnValue , DbType . Int32 , null ) ;
command . ExecuteNonQuery ( ) ;
int returnValue = GetReturnValue ( retValue ) ;
if ( returnValue = = 0 )
return newPassword ;
else if ( returnValue = = 3 )
throw new MembershipPasswordException ( "Password Answer is invalid" ) ;
else if ( returnValue = = 99 )
throw new MembershipPasswordException ( "The user account is currently locked out" ) ;
else
throw new ProviderException ( "Failed to reset password" ) ;
}
}
public override void UpdateUser ( MembershipUser user )
{
if ( user = = null )
throw new ArgumentNullException ( "user" ) ;
if ( user . UserName = = null )
throw new ArgumentNullException ( "user.UserName" ) ;
if ( RequiresUniqueEmail & & user . Email = = null )
throw new ArgumentNullException ( "user.Email" ) ;
CheckParam ( "user.UserName" , user . UserName , 256 ) ;
if ( user . Email . Length > 256 | | ( RequiresUniqueEmail & & user . Email . Length = = 0 ) )
throw new ArgumentException ( "invalid format for user.Email" ) ;
using ( DbConnection connection = CreateConnection ( ) ) {
int returnValue = 0 ;
DbCommand command = factory . CreateCommand ( ) ;
command . Connection = connection ;
command . CommandText = @"aspnet_Membership_UpdateUser" ;
command . CommandType = CommandType . StoredProcedure ;
AddParameter ( command , "@ApplicationName" , ApplicationName ) ;
AddParameter ( command , "@UserName" , user . UserName ) ;
AddParameter ( command , "@Email" , user . Email = = null ? ( object ) DBNull . Value : ( object ) user . Email ) ;
AddParameter ( command , "@Comment" , user . Comment = = null ? ( object ) DBNull . Value : ( object ) user . Comment ) ;
AddParameter ( command , "@IsApproved" , user . IsApproved ) ;
AddParameter ( command , "@LastLoginDate" , DateTime . UtcNow ) ;
AddParameter ( command , "@LastActivityDate" , DateTime . UtcNow ) ;
AddParameter ( command , "@UniqueEmail" , RequiresUniqueEmail ) ;
AddParameter ( command , "@CurrentTimeUtc" , DateTime . UtcNow ) ;
DbParameter retValue = AddParameter ( command , "@ReturnVal" , ParameterDirection . ReturnValue , DbType . Int32 , null ) ;
command . ExecuteNonQuery ( ) ;
returnValue = GetReturnValue ( retValue ) ;
if ( returnValue = = 1 )
throw new ProviderException ( "The UserName property of user was not found in the database." ) ;
if ( returnValue = = 7 )
throw new ProviderException ( "The Email property of user was equal to an existing e-mail address in the database and RequiresUniqueEmail is set to true." ) ;
if ( returnValue ! = 0 )
throw new ProviderException ( "Failed to update user" ) ;
}
}
public override bool ValidateUser ( string username , string password )
{
if ( username . Length = = 0 )
return false ;
CheckParam ( "username" , username , 256 ) ;
EmitValidatingPassword ( username , password , false ) ;
PasswordInfo pi = ValidateUsingPassword ( username , password ) ;
if ( pi ! = null ) {
pi . LastLoginDate = DateTime . UtcNow ;
UpdateUserInfo ( username , pi , true , true ) ;
return true ;
}
return false ;
}
public override bool UnlockUser ( string username )
{
CheckParam ( "username" , username , 256 ) ;
using ( DbConnection connection = CreateConnection ( ) ) {
try {
DbCommand command = factory . CreateCommand ( ) ;
command . Connection = connection ;
command . CommandText = @"aspnet_Membership_UnlockUser" ; ;
command . CommandType = CommandType . StoredProcedure ;
AddParameter ( command , "@ApplicationName" , ApplicationName ) ;
AddParameter ( command , "@UserName" , username ) ;
DbParameter returnValue = AddParameter ( command , "@ReturnVal" , ParameterDirection . ReturnValue , DbType . Int32 , null ) ;
command . ExecuteNonQuery ( ) ;
if ( GetReturnValue ( returnValue ) ! = 0 )
return false ;
}
catch ( Exception e ) {
throw new ProviderException ( "Failed to unlock user" , e ) ;
}
}
return true ;
}
void UpdateUserInfo ( string username , PasswordInfo pi , bool isPasswordCorrect , bool updateLoginActivity )
{
CheckParam ( "username" , username , 256 ) ;
using ( DbConnection connection = CreateConnection ( ) ) {
try {
DbCommand command = factory . CreateCommand ( ) ;
command . Connection = connection ;
command . CommandText = @"aspnet_Membership_UpdateUserInfo" ; ;
command . CommandType = CommandType . StoredProcedure ;
AddParameter ( command , "@ApplicationName" , ApplicationName ) ;
AddParameter ( command , "@UserName" , username ) ;
AddParameter ( command , "@IsPasswordCorrect" , isPasswordCorrect ) ;
AddParameter ( command , "@UpdateLastLoginActivityDate" , updateLoginActivity ) ;
AddParameter ( command , "@MaxInvalidPasswordAttempts" , MaxInvalidPasswordAttempts ) ;
AddParameter ( command , "@PasswordAttemptWindow" , PasswordAttemptWindow ) ;
AddParameter ( command , "@CurrentTimeUtc" , DateTime . UtcNow ) ;
AddParameter ( command , "@LastLoginDate" , pi . LastLoginDate ) ;
AddParameter ( command , "@LastActivityDate" , pi . LastActivityDate ) ;
DbParameter retValue = AddParameter ( command , "@ReturnVal" , ParameterDirection . ReturnValue , DbType . Int32 , null ) ;
command . ExecuteNonQuery ( ) ;
int returnValue = GetReturnValue ( retValue ) ;
if ( returnValue ! = 0 )
return ;
}
catch ( Exception e ) {
throw new ProviderException ( "Failed to update Membership table" , e ) ;
}
}
}
PasswordInfo ValidateUsingPassword ( string username , string password )
{
MembershipUser user = GetUser ( username , true ) ;
if ( user = = null )
return null ;
if ( ! user . IsApproved | | user . IsLockedOut )
return null ;
PasswordInfo pi = GetPasswordInfo ( username ) ;
if ( pi = = null )
return null ;
/* do the actual validation */
string user_password = EncodePassword ( password , pi . PasswordFormat , pi . PasswordSalt ) ;
if ( user_password ! = pi . Password ) {
UpdateUserInfo ( username , pi , false , false ) ;
return null ;
}
return pi ;
}
PasswordInfo GetPasswordInfo ( string username )
{
using ( DbConnection connection = CreateConnection ( ) ) {
DbCommand command = factory . CreateCommand ( ) ;
command . Connection = connection ;
command . CommandType = CommandType . StoredProcedure ;
command . CommandText = @"aspnet_Membership_GetPasswordWithFormat" ;
AddParameter ( command , "@ApplicationName" , ApplicationName ) ;
AddParameter ( command , "@UserName" , username ) ;
AddParameter ( command , "@UpdateLastLoginActivityDate" , false ) ;
AddParameter ( command , "@CurrentTimeUtc" , DateTime . Now ) ;
// return value
AddParameter ( command , "@ReturnVal" , ParameterDirection . ReturnValue , DbType . Int32 , null ) ;
DbDataReader reader = command . ExecuteReader ( ) ;
if ( ! reader . Read ( ) )
return null ;
PasswordInfo pi = new PasswordInfo (
reader . GetString ( 0 ) ,
( MembershipPasswordFormat ) reader . GetInt32 ( 1 ) ,
reader . GetString ( 2 ) ,
reader . GetInt32 ( 3 ) ,
reader . GetInt32 ( 4 ) ,
reader . GetBoolean ( 5 ) ,
reader . GetDateTime ( 6 ) ,
reader . GetDateTime ( 7 ) ) ;
return pi ;
}
}
string EncodePassword ( string password , MembershipPasswordFormat passwordFormat , string salt )
{
byte [ ] password_bytes ;
byte [ ] salt_bytes ;
switch ( passwordFormat ) {
case MembershipPasswordFormat . Clear :
return password ;
case MembershipPasswordFormat . Hashed :
password_bytes = Encoding . Unicode . GetBytes ( password ) ;
salt_bytes = Convert . FromBase64String ( salt ) ;
byte [ ] hashBytes = new byte [ salt_bytes . Length + password_bytes . Length ] ;
Buffer . BlockCopy ( salt_bytes , 0 , hashBytes , 0 , salt_bytes . Length ) ;
Buffer . BlockCopy ( password_bytes , 0 , hashBytes , salt_bytes . Length , password_bytes . Length ) ;
MembershipSection section = ( MembershipSection ) WebConfigurationManager . GetSection ( "system.web/membership" ) ;
string alg_type = section . HashAlgorithmType ;
if ( alg_type . Length = = 0 ) {
alg_type = MachineKeySection . Config . Validation . ToString ( ) ;
// support new (4.0) custom algorithms
if ( alg_type . StartsWith ( "alg:" ) )
alg_type = alg_type . Substring ( 4 ) ;
}
using ( HashAlgorithm hash = HashAlgorithm . Create ( alg_type ) ) {
// for compatibility (with 2.0) we'll allow MD5 and SHA1 not to map to HMACMD5 and HMACSHA1
// but that won't work with new (4.0) algorithms, like HMACSHA256|384|512 or custom, won't work without using the key
KeyedHashAlgorithm kha = ( hash as KeyedHashAlgorithm ) ;
if ( kha ! = null )
kha . Key = MachineKeySection . Config . GetValidationKey ( ) ;
hash . TransformFinalBlock ( hashBytes , 0 , hashBytes . Length ) ;
return Convert . ToBase64String ( hash . Hash ) ;
}
case MembershipPasswordFormat . Encrypted :
password_bytes = Encoding . Unicode . GetBytes ( password ) ;
salt_bytes = Convert . FromBase64String ( salt ) ;
byte [ ] buf = new byte [ password_bytes . Length + salt_bytes . Length ] ;
Array . Copy ( salt_bytes , 0 , buf , 0 , salt_bytes . Length ) ;
Array . Copy ( password_bytes , 0 , buf , salt_bytes . Length , password_bytes . Length ) ;
return Convert . ToBase64String ( EncryptPassword ( buf ) ) ;
default :
/* not reached.. */
return null ;
}
}
string DecodePassword ( string password , MembershipPasswordFormat passwordFormat )
{
switch ( passwordFormat ) {
case MembershipPasswordFormat . Clear :
return password ;
case MembershipPasswordFormat . Hashed :
throw new ProviderException ( "Hashed passwords cannot be decoded." ) ;
case MembershipPasswordFormat . Encrypted :
return Encoding . Unicode . GetString ( DecryptPassword ( Convert . FromBase64String ( password ) ) ) ;
default :
/* not reached.. */
return null ;
}
}
public override string ApplicationName
{
get { return applicationName ; }
set { applicationName = value ; }
}
public override bool EnablePasswordReset
{
get { return enablePasswordReset ; }
}
public override bool EnablePasswordRetrieval
{
get { return enablePasswordRetrieval ; }
}
public override MembershipPasswordFormat PasswordFormat
{
get { return passwordFormat ; }
}
public override bool RequiresQuestionAndAnswer
{
get { return requiresQuestionAndAnswer ; }
}
public override bool RequiresUniqueEmail
{
get { return requiresUniqueEmail ; }
}
public override int MaxInvalidPasswordAttempts
{
get { return maxInvalidPasswordAttempts ; }
}
public override int MinRequiredNonAlphanumericCharacters
{
get { return minRequiredNonAlphanumericCharacters ; }
}
public override int MinRequiredPasswordLength
{
get { return minRequiredPasswordLength ; }
}
public override int PasswordAttemptWindow
{
get { return passwordAttemptWindow ; }
}
public override string PasswordStrengthRegularExpression
{
get { return passwordStrengthRegularExpression ; }
}
[Flags]
enum DeleteUserTableMask
{
MembershipUsers = 1 ,
UsersInRoles = 2 ,
Profiles = 4 ,
WebPartStateUser = 8
}
sealed class PasswordInfo
{
string _password ;
MembershipPasswordFormat _passwordFormat ;
string _passwordSalt ;
int _failedPasswordAttemptCount ;
int _failedPasswordAnswerAttemptCount ;
bool _isApproved ;
DateTime _lastLoginDate ;
DateTime _lastActivityDate ;
internal PasswordInfo (
string password ,
MembershipPasswordFormat passwordFormat ,
string passwordSalt ,
int failedPasswordAttemptCount ,
int failedPasswordAnswerAttemptCount ,
bool isApproved ,
DateTime lastLoginDate ,
DateTime lastActivityDate )
{
_password = password ;
_passwordFormat = passwordFormat ;
_passwordSalt = passwordSalt ;
_failedPasswordAttemptCount = failedPasswordAttemptCount ;
_failedPasswordAnswerAttemptCount = failedPasswordAnswerAttemptCount ;
_isApproved = isApproved ;
_lastLoginDate = lastLoginDate ;
_lastActivityDate = lastActivityDate ;
}
public string Password
{
get { return _password ; }
set { _password = value ; }
}
public MembershipPasswordFormat PasswordFormat
{
get { return _passwordFormat ; }
set { _passwordFormat = value ; }
}
public string PasswordSalt
{
get { return _passwordSalt ; }
set { _passwordSalt = value ; }
}
public int FailedPasswordAttemptCount
{
get { return _failedPasswordAttemptCount ; }
set { _failedPasswordAttemptCount = value ; }
}
public int FailedPasswordAnswerAttemptCount
{
get { return _failedPasswordAnswerAttemptCount ; }
set { _failedPasswordAnswerAttemptCount = value ; }
}
public bool IsApproved
{
get { return _isApproved ; }
set { _isApproved = value ; }
}
public DateTime LastLoginDate
{
get { return _lastLoginDate ; }
set { _lastLoginDate = value ; }
}
public DateTime LastActivityDate
{
get { return _lastActivityDate ; }
set { _lastActivityDate = value ; }
}
}
}
}