SqlMembershipProvider.cs 41 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210
  1. //
  2. // System.Web.Security.SqlMembershipProvider
  3. //
  4. // Authors:
  5. // Ben Maurer ([email protected])
  6. // Lluis Sanchez Gual ([email protected])
  7. // Chris Toshok ([email protected])
  8. //
  9. // (C) 2003 Ben Maurer
  10. // Copyright (c) 2005,2006 Novell, Inc (http://www.novell.com)
  11. //
  12. // Permission is hereby granted, free of charge, to any person obtaining
  13. // a copy of this software and associated documentation files (the
  14. // "Software"), to deal in the Software without restriction, including
  15. // without limitation the rights to use, copy, modify, merge, publish,
  16. // distribute, sublicense, and/or sell copies of the Software, and to
  17. // permit persons to whom the Software is furnished to do so, subject to
  18. // the following conditions:
  19. //
  20. // The above copyright notice and this permission notice shall be
  21. // included in all copies or substantial portions of the Software.
  22. //
  23. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  24. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  25. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  26. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  27. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  28. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  29. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  30. //
  31. #if NET_2_0
  32. using System.Collections;
  33. using System.Collections.Specialized;
  34. using System.Configuration;
  35. using System.Configuration.Provider;
  36. using System.Data;
  37. using System.Data.Common;
  38. using System.Text;
  39. using System.Web.Configuration;
  40. using System.Security.Cryptography;
  41. namespace System.Web.Security {
  42. public class SqlMembershipProvider : MembershipProvider
  43. {
  44. bool enablePasswordReset;
  45. bool enablePasswordRetrieval;
  46. int maxInvalidPasswordAttempts;
  47. MembershipPasswordFormat passwordFormat;
  48. bool requiresQuestionAndAnswer;
  49. bool requiresUniqueEmail;
  50. int minRequiredNonAlphanumericCharacters;
  51. int minRequiredPasswordLength;
  52. int passwordAttemptWindow;
  53. string passwordStrengthRegularExpression;
  54. TimeSpan userIsOnlineTimeWindow;
  55. ConnectionStringSettings connectionString;
  56. DbProviderFactory factory;
  57. string applicationName;
  58. DbConnection CreateConnection ()
  59. {
  60. DbConnection connection = factory.CreateConnection ();
  61. connection.ConnectionString = connectionString.ConnectionString;
  62. connection.Open ();
  63. return connection;
  64. }
  65. DbParameter AddParameter (DbCommand command, string parameterName, object parameterValue)
  66. {
  67. return AddParameter (command, parameterName, ParameterDirection.Input, parameterValue);
  68. }
  69. DbParameter AddParameter (DbCommand command, string parameterName, ParameterDirection direction, object parameterValue)
  70. {
  71. DbParameter dbp = command.CreateParameter ();
  72. dbp.ParameterName = parameterName;
  73. dbp.Value = parameterValue;
  74. dbp.Direction = direction;
  75. command.Parameters.Add (dbp);
  76. return dbp;
  77. }
  78. DbParameter AddParameter (DbCommand command, string parameterName, ParameterDirection direction, DbType type, object parameterValue)
  79. {
  80. DbParameter dbp = command.CreateParameter ();
  81. dbp.ParameterName = parameterName;
  82. dbp.Value = parameterValue;
  83. dbp.Direction = direction;
  84. dbp.DbType = type;
  85. command.Parameters.Add (dbp);
  86. return dbp;
  87. }
  88. static int GetReturnValue (DbParameter returnValue)
  89. {
  90. object value = returnValue.Value;
  91. return value is int ? (int) value : -1;
  92. }
  93. void CheckParam (string pName, string p, int length)
  94. {
  95. if (p == null)
  96. throw new ArgumentNullException (pName);
  97. if (p.Length == 0 || p.Length > length || p.IndexOf (",") != -1)
  98. throw new ArgumentException (String.Format ("invalid format for {0}", pName));
  99. }
  100. public override bool ChangePassword (string username, string oldPwd, string newPwd)
  101. {
  102. if (username != null) username = username.Trim ();
  103. if (oldPwd != null) oldPwd = oldPwd.Trim ();
  104. if (newPwd != null) newPwd = newPwd.Trim ();
  105. CheckParam ("username", username, 256);
  106. CheckParam ("oldPwd", oldPwd, 128);
  107. CheckParam ("newPwd", newPwd, 128);
  108. using (DbConnection connection = CreateConnection ()) {
  109. PasswordInfo pi = ValidateUsingPassword (username, oldPwd);
  110. if (pi != null) {
  111. EmitValidatingPassword (username, newPwd, false);
  112. string db_password = EncodePassword (newPwd, pi.PasswordFormat, pi.PasswordSalt);
  113. DbCommand command = factory.CreateCommand ();
  114. command.Connection = connection;
  115. command.CommandText = @"aspnet_Membership_SetPassword";
  116. command.CommandType = CommandType.StoredProcedure;
  117. AddParameter (command, "@ApplicationName", ApplicationName);
  118. AddParameter (command, "@UserName", username);
  119. AddParameter (command, "@NewPassword", db_password);
  120. AddParameter (command, "@PasswordFormat", (int) pi.PasswordFormat);
  121. AddParameter (command, "@PasswordSalt", pi.PasswordSalt);
  122. AddParameter (command, "@CurrentTimeUtc", DateTime.UtcNow);
  123. DbParameter returnValue = AddParameter (command, "@ReturnVal", ParameterDirection.ReturnValue, DbType.Int32, null);
  124. command.ExecuteNonQuery ();
  125. if (GetReturnValue (returnValue) != 0)
  126. return false;
  127. return true;
  128. }
  129. return false;
  130. }
  131. }
  132. public override bool ChangePasswordQuestionAndAnswer (string username, string password, string newPwdQuestion, string newPwdAnswer)
  133. {
  134. if (username != null) username = username.Trim ();
  135. if (newPwdQuestion != null) newPwdQuestion = newPwdQuestion.Trim ();
  136. if (newPwdAnswer != null) newPwdAnswer = newPwdAnswer.Trim ();
  137. CheckParam ("username", username, 256);
  138. if (RequiresQuestionAndAnswer)
  139. CheckParam ("newPwdQuestion", newPwdQuestion, 128);
  140. if (RequiresQuestionAndAnswer)
  141. CheckParam ("newPwdAnswer", newPwdAnswer, 128);
  142. using (DbConnection connection = CreateConnection ()) {
  143. PasswordInfo pi = ValidateUsingPassword (username, password);
  144. if (pi != null) {
  145. string db_passwordAnswer = EncodePassword (newPwdAnswer, pi.PasswordFormat, pi.PasswordSalt);
  146. DbCommand command = factory.CreateCommand ();
  147. command.Connection = connection;
  148. command.CommandType = CommandType.StoredProcedure;
  149. command.CommandText = @"aspnet_Membership_ChangePasswordQuestionAndAnswer";
  150. AddParameter (command, "@ApplicationName", ApplicationName);
  151. AddParameter (command, "@UserName", username);
  152. AddParameter (command, "@NewPasswordQuestion", newPwdQuestion);
  153. AddParameter (command, "@NewPasswordAnswer", db_passwordAnswer);
  154. DbParameter returnValue = AddParameter (command, "@ReturnVal", ParameterDirection.ReturnValue, DbType.Int32, null);
  155. command.ExecuteNonQuery ();
  156. if (GetReturnValue (returnValue) != 0)
  157. return false;
  158. return true;
  159. }
  160. return false;
  161. }
  162. }
  163. public override MembershipUser CreateUser (string username,
  164. string password,
  165. string email,
  166. string pwdQuestion,
  167. string pwdAnswer,
  168. bool isApproved,
  169. object providerUserKey,
  170. out MembershipCreateStatus status)
  171. {
  172. if (username != null) username = username.Trim ();
  173. if (password != null) password = password.Trim ();
  174. if (email != null) email = email.Trim ();
  175. if (pwdQuestion != null) pwdQuestion = pwdQuestion.Trim ();
  176. if (pwdAnswer != null) pwdAnswer = pwdAnswer.Trim ();
  177. /* some initial validation */
  178. if (username == null || username.Length == 0 || username.Length > 256 || username.IndexOf (",") != -1) {
  179. status = MembershipCreateStatus.InvalidUserName;
  180. return null;
  181. }
  182. if (password == null || password.Length == 0 || password.Length > 128) {
  183. status = MembershipCreateStatus.InvalidPassword;
  184. return null;
  185. }
  186. if (!CheckPassword (password)) {
  187. status = MembershipCreateStatus.InvalidPassword;
  188. return null;
  189. }
  190. EmitValidatingPassword (username, password, true);
  191. if (RequiresUniqueEmail && (email == null || email.Length == 0)) {
  192. status = MembershipCreateStatus.InvalidEmail;
  193. return null;
  194. }
  195. if (RequiresQuestionAndAnswer &&
  196. (pwdQuestion == null ||
  197. pwdQuestion.Length == 0 || pwdQuestion.Length > 256)) {
  198. status = MembershipCreateStatus.InvalidQuestion;
  199. return null;
  200. }
  201. if (RequiresQuestionAndAnswer &&
  202. (pwdAnswer == null ||
  203. pwdAnswer.Length == 0 || pwdAnswer.Length > 128)) {
  204. status = MembershipCreateStatus.InvalidAnswer;
  205. return null;
  206. }
  207. if (providerUserKey != null && !(providerUserKey is Guid)) {
  208. status = MembershipCreateStatus.InvalidProviderUserKey;
  209. return null;
  210. }
  211. if (providerUserKey == null)
  212. providerUserKey = Guid.NewGuid();
  213. /* encode our password/answer using the
  214. * "passwordFormat" configuration option */
  215. string passwordSalt = "";
  216. RandomNumberGenerator rng = RandomNumberGenerator.Create ();
  217. byte [] salt = new byte [SALT_BYTES];
  218. rng.GetBytes (salt);
  219. passwordSalt = Convert.ToBase64String (salt);
  220. password = EncodePassword (password, PasswordFormat, passwordSalt);
  221. if (RequiresQuestionAndAnswer)
  222. pwdAnswer = EncodePassword (pwdAnswer, PasswordFormat, passwordSalt);
  223. /* make sure the hashed/encrypted password and
  224. * answer are still under 128 characters. */
  225. if (password.Length > 128) {
  226. status = MembershipCreateStatus.InvalidPassword;
  227. return null;
  228. }
  229. if (RequiresQuestionAndAnswer) {
  230. if (pwdAnswer.Length > 128) {
  231. status = MembershipCreateStatus.InvalidAnswer;
  232. return null;
  233. }
  234. }
  235. status = MembershipCreateStatus.Success;
  236. using (DbConnection connection = CreateConnection ()) {
  237. try {
  238. DbCommand command = factory.CreateCommand ();
  239. command.Connection = connection;
  240. command.CommandText = @"aspnet_Membership_CreateUser";
  241. command.CommandType = CommandType.StoredProcedure;
  242. DateTime Now = DateTime.UtcNow;
  243. AddParameter (command, "@ApplicationName", ApplicationName);
  244. AddParameter (command, "@UserName", username);
  245. AddParameter (command, "@Password", password);
  246. AddParameter (command, "@PasswordSalt", passwordSalt);
  247. AddParameter (command, "@Email", email);
  248. AddParameter (command, "@PasswordQuestion", pwdQuestion);
  249. AddParameter (command, "@PasswordAnswer", pwdAnswer);
  250. AddParameter (command, "@IsApproved", isApproved);
  251. AddParameter (command, "@CurrentTimeUtc", Now);
  252. AddParameter (command, "@CreateDate", Now);
  253. AddParameter (command, "@UniqueEmail", RequiresUniqueEmail);
  254. AddParameter (command, "@PasswordFormat", (int) PasswordFormat);
  255. AddParameter (command, "@UserId", ParameterDirection.InputOutput, providerUserKey);
  256. DbParameter returnValue = AddParameter (command, "@ReturnVal", ParameterDirection.ReturnValue, DbType.Int32, null);
  257. command.ExecuteNonQuery ();
  258. int st = GetReturnValue (returnValue);
  259. if (st == 0)
  260. return GetUser (username, false);
  261. else if (st == 6)
  262. status = MembershipCreateStatus.DuplicateUserName;
  263. else if (st == 7)
  264. status = MembershipCreateStatus.DuplicateEmail;
  265. else if (st == 10)
  266. status = MembershipCreateStatus.DuplicateProviderUserKey;
  267. else
  268. status = MembershipCreateStatus.ProviderError;
  269. return null;
  270. }
  271. catch (Exception) {
  272. status = MembershipCreateStatus.ProviderError;
  273. return null;
  274. }
  275. }
  276. }
  277. private bool CheckPassword (string password)
  278. {
  279. if (password.Length < MinRequiredPasswordLength)
  280. return false;
  281. if (MinRequiredNonAlphanumericCharacters > 0) {
  282. int nonAlphanumeric = 0;
  283. for (int i = 0; i < password.Length; i++) {
  284. if (!Char.IsLetterOrDigit (password [i]))
  285. nonAlphanumeric++;
  286. }
  287. return nonAlphanumeric >= MinRequiredNonAlphanumericCharacters;
  288. }
  289. return true;
  290. }
  291. public override bool DeleteUser (string username, bool deleteAllRelatedData)
  292. {
  293. CheckParam ("username", username, 256);
  294. DeleteUserTableMask deleteBitmask = DeleteUserTableMask.MembershipUsers;
  295. if (deleteAllRelatedData)
  296. deleteBitmask |=
  297. DeleteUserTableMask.Profiles |
  298. DeleteUserTableMask.UsersInRoles |
  299. DeleteUserTableMask.WebPartStateUser;
  300. using (DbConnection connection = CreateConnection ()) {
  301. DbCommand command = factory.CreateCommand ();
  302. command.Connection = connection;
  303. command.CommandText = @"aspnet_Users_DeleteUser";
  304. command.CommandType = CommandType.StoredProcedure;
  305. AddParameter (command, "@ApplicationName", ApplicationName);
  306. AddParameter (command, "@UserName", username);
  307. AddParameter (command, "@TablesToDeleteFrom", (int) deleteBitmask);
  308. AddParameter (command, "@NumTablesDeletedFrom", ParameterDirection.Output, 0);
  309. DbParameter returnValue = AddParameter (command, "@ReturnVal", ParameterDirection.ReturnValue, DbType.Int32, null);
  310. command.ExecuteNonQuery ();
  311. if (((int) command.Parameters ["NumTablesDeletedFrom"].Value) == 0)
  312. return false;
  313. if (GetReturnValue (returnValue) == 0)
  314. return true;
  315. return false;
  316. }
  317. }
  318. public virtual string GeneratePassword ()
  319. {
  320. return Membership.GeneratePassword (MinRequiredPasswordLength, MinRequiredNonAlphanumericCharacters);
  321. }
  322. public override MembershipUserCollection FindUsersByEmail (string emailToMatch, int pageIndex, int pageSize, out int totalRecords)
  323. {
  324. CheckParam ("emailToMatch", emailToMatch, 256);
  325. if (pageIndex < 0)
  326. throw new ArgumentException ("pageIndex must be >= 0");
  327. if (pageSize < 0)
  328. throw new ArgumentException ("pageSize must be >= 0");
  329. if (pageIndex * pageSize + pageSize - 1 > Int32.MaxValue)
  330. throw new ArgumentException ("pageIndex and pageSize are too large");
  331. using (DbConnection connection = CreateConnection ()) {
  332. DbCommand command = factory.CreateCommand ();
  333. command.Connection = connection;
  334. command.CommandText = @"aspnet_Membership_FindUsersByEmail";
  335. command.CommandType = CommandType.StoredProcedure;
  336. AddParameter (command, "@PageIndex", pageIndex);
  337. AddParameter (command, "@PageSize", pageSize);
  338. AddParameter (command, "@EmailToMatch", emailToMatch);
  339. AddParameter (command, "@ApplicationName", ApplicationName);
  340. // return value
  341. AddParameter (command, "@ReturnValue", ParameterDirection.ReturnValue, null);
  342. MembershipUserCollection c = BuildMembershipUserCollection (command, pageIndex, pageSize, out totalRecords);
  343. return c;
  344. }
  345. }
  346. public override MembershipUserCollection FindUsersByName (string nameToMatch, int pageIndex, int pageSize, out int totalRecords)
  347. {
  348. CheckParam ("nameToMatch", nameToMatch, 256);
  349. if (pageIndex < 0)
  350. throw new ArgumentException ("pageIndex must be >= 0");
  351. if (pageSize < 0)
  352. throw new ArgumentException ("pageSize must be >= 0");
  353. if (pageIndex * pageSize + pageSize - 1 > Int32.MaxValue)
  354. throw new ArgumentException ("pageIndex and pageSize are too large");
  355. using (DbConnection connection = CreateConnection ()) {
  356. DbCommand command = factory.CreateCommand ();
  357. command.Connection = connection;
  358. command.CommandText = @"aspnet_Membership_FindUsersByName";
  359. command.CommandType = CommandType.StoredProcedure;
  360. AddParameter (command, "@PageIndex", pageIndex);
  361. AddParameter (command, "@PageSize", pageSize);
  362. AddParameter (command, "@UserNameToMatch", nameToMatch);
  363. AddParameter (command, "@ApplicationName", ApplicationName);
  364. // return value
  365. AddParameter (command, "@ReturnValue", ParameterDirection.ReturnValue, null);
  366. MembershipUserCollection c = BuildMembershipUserCollection (command, pageIndex, pageSize, out totalRecords);
  367. return c;
  368. }
  369. }
  370. public override MembershipUserCollection GetAllUsers (int pageIndex, int pageSize, out int totalRecords)
  371. {
  372. if (pageIndex < 0)
  373. throw new ArgumentException ("pageIndex must be >= 0");
  374. if (pageSize < 0)
  375. throw new ArgumentException ("pageSize must be >= 0");
  376. if (pageIndex * pageSize + pageSize - 1 > Int32.MaxValue)
  377. throw new ArgumentException ("pageIndex and pageSize are too large");
  378. using (DbConnection connection = CreateConnection ()) {
  379. DbCommand command = factory.CreateCommand ();
  380. command.Connection = connection;
  381. command.CommandText = @"aspnet_Membership_GetAllUsers";
  382. command.CommandType = CommandType.StoredProcedure;
  383. AddParameter (command, "@ApplicationName", ApplicationName);
  384. AddParameter (command, "@PageIndex", pageIndex);
  385. AddParameter (command, "@PageSize", pageSize);
  386. // return value
  387. AddParameter (command, "@ReturnValue", ParameterDirection.ReturnValue, null);
  388. MembershipUserCollection c = BuildMembershipUserCollection (command, pageIndex, pageSize, out totalRecords);
  389. return c;
  390. }
  391. }
  392. MembershipUserCollection BuildMembershipUserCollection (DbCommand command, int pageIndex, int pageSize, out int totalRecords)
  393. {
  394. DbDataReader reader = null;
  395. try {
  396. MembershipUserCollection users = new MembershipUserCollection ();
  397. reader = command.ExecuteReader ();
  398. while (reader.Read ())
  399. users.Add (GetUserFromReader (reader, null, null));
  400. totalRecords = Convert.ToInt32 (command.Parameters ["ReturnValue"].Value);
  401. return users;
  402. } catch (Exception) {
  403. totalRecords = 0;
  404. return null; /* should we let the exception through? */
  405. }
  406. finally {
  407. if (reader != null)
  408. reader.Close ();
  409. }
  410. }
  411. public override int GetNumberOfUsersOnline ()
  412. {
  413. using (DbConnection connection = CreateConnection ()) {
  414. DateTime now = DateTime.UtcNow;
  415. DbCommand command = factory.CreateCommand ();
  416. command.Connection = connection;
  417. command.CommandText = @"aspnet_Membership_GetNumberOfUsersOnline";
  418. command.CommandType = CommandType.StoredProcedure;
  419. AddParameter (command, "@CurrentTimeUtc", now.ToString ());
  420. AddParameter (command, "@ApplicationName", ApplicationName);
  421. AddParameter (command, "@MinutesSinceLastInActive", userIsOnlineTimeWindow.Minutes);
  422. DbParameter returnValue = AddParameter (command, "@ReturnVal", ParameterDirection.ReturnValue, DbType.Int32, null);
  423. command.ExecuteScalar ();
  424. return GetReturnValue (returnValue);
  425. }
  426. }
  427. public override string GetPassword (string username, string answer)
  428. {
  429. if (!EnablePasswordRetrieval)
  430. throw new NotSupportedException ("this provider has not been configured to allow the retrieval of passwords");
  431. CheckParam ("username", username, 256);
  432. if (RequiresQuestionAndAnswer)
  433. CheckParam ("answer", answer, 128);
  434. PasswordInfo pi = GetPasswordInfo (username);
  435. if (pi == null)
  436. throw new ProviderException ("An error occurred while retrieving the password from the database");
  437. string user_answer = EncodePassword (answer, pi.PasswordFormat, pi.PasswordSalt);
  438. string password = null;
  439. using (DbConnection connection = CreateConnection ()) {
  440. DbCommand command = factory.CreateCommand ();
  441. command.Connection = connection;
  442. command.CommandText = @"aspnet_Membership_GetPassword";
  443. command.CommandType = CommandType.StoredProcedure;
  444. AddParameter (command, "@ApplicationName", ApplicationName);
  445. AddParameter (command, "@UserName", username);
  446. AddParameter (command, "@MaxInvalidPasswordAttempts", MaxInvalidPasswordAttempts);
  447. AddParameter (command, "@PasswordAttemptWindow", PasswordAttemptWindow);
  448. AddParameter (command, "@CurrentTimeUtc", DateTime.UtcNow);
  449. AddParameter (command, "@PasswordAnswer", user_answer);
  450. DbParameter retValue = AddParameter (command, "@ReturnVal", ParameterDirection.ReturnValue, DbType.Int32, null);
  451. DbDataReader reader = command.ExecuteReader ();
  452. int returnValue = GetReturnValue (retValue);
  453. if (returnValue == 3)
  454. throw new MembershipPasswordException ("Password Answer is invalid");
  455. if (returnValue == 99)
  456. throw new MembershipPasswordException ("The user account is currently locked out");
  457. if (reader.Read ()) {
  458. password = reader.GetString (0);
  459. reader.Close ();
  460. }
  461. if (pi.PasswordFormat == MembershipPasswordFormat.Clear)
  462. return password;
  463. else if (pi.PasswordFormat == MembershipPasswordFormat.Encrypted)
  464. return DecodePassword (password, pi.PasswordFormat);
  465. return password;
  466. }
  467. }
  468. MembershipUser GetUserFromReader (DbDataReader reader, string username, object userId)
  469. {
  470. int i = 0;
  471. if (username == null)
  472. i = 1;
  473. if (userId != null)
  474. username = reader.GetString (8);
  475. return new MembershipUser (this.Name, /* XXX is this right? */
  476. (username == null ? reader.GetString (0) : username), /* name */
  477. (userId == null ? reader.GetGuid (8 + i) : userId), /* providerUserKey */
  478. reader.IsDBNull (0 + i) ? null : reader.GetString (0 + i), /* email */
  479. reader.IsDBNull (1 + i) ? null : reader.GetString (1 + i), /* passwordQuestion */
  480. reader.IsDBNull (2 + i) ? null : reader.GetString (2 + i), /* comment */
  481. reader.GetBoolean (3 + i), /* isApproved */
  482. reader.GetBoolean (9 + i), /* isLockedOut */
  483. reader.GetDateTime (4 + i).ToLocalTime (), /* creationDate */
  484. reader.GetDateTime (5 + i).ToLocalTime (), /* lastLoginDate */
  485. reader.GetDateTime (6 + i).ToLocalTime (), /* lastActivityDate */
  486. reader.GetDateTime (7 + i).ToLocalTime (), /* lastPasswordChangedDate */
  487. reader.GetDateTime (10 + i).ToLocalTime () /* lastLockoutDate */);
  488. }
  489. MembershipUser BuildMembershipUser (DbCommand query, string username, object userId)
  490. {
  491. try {
  492. using (DbConnection connection = CreateConnection ()) {
  493. query.Connection = connection;
  494. using (DbDataReader reader = query.ExecuteReader ()) {
  495. if (!reader.Read ())
  496. return null;
  497. return GetUserFromReader (reader, username, userId);
  498. }
  499. }
  500. } catch (Exception) {
  501. return null; /* should we let the exception through? */
  502. }
  503. finally {
  504. query.Connection = null;
  505. }
  506. }
  507. public override MembershipUser GetUser (string username, bool userIsOnline)
  508. {
  509. if (username == null)
  510. throw new ArgumentNullException ("username");
  511. if (username.Length == 0)
  512. return null;
  513. CheckParam ("username", username, 256);
  514. DbCommand command = factory.CreateCommand ();
  515. command.CommandText = @"aspnet_Membership_GetUserByName";
  516. command.CommandType = CommandType.StoredProcedure;
  517. AddParameter (command, "@UserName", username);
  518. AddParameter (command, "@ApplicationName", ApplicationName);
  519. AddParameter (command, "@CurrentTimeUtc", DateTime.Now);
  520. AddParameter (command, "@UpdateLastActivity", userIsOnline);
  521. MembershipUser u = BuildMembershipUser (command, username, null);
  522. return u;
  523. }
  524. public override MembershipUser GetUser (object providerUserKey, bool userIsOnline)
  525. {
  526. DbCommand command = factory.CreateCommand ();
  527. command.CommandText = @"aspnet_Membership_GetUserByUserId";
  528. command.CommandType = CommandType.StoredProcedure;
  529. AddParameter (command, "@UserId", providerUserKey);
  530. AddParameter (command, "@CurrentTimeUtc", DateTime.Now);
  531. AddParameter (command, "@UpdateLastActivity", userIsOnline);
  532. MembershipUser u = BuildMembershipUser (command, string.Empty, providerUserKey);
  533. return u;
  534. }
  535. public override string GetUserNameByEmail (string email)
  536. {
  537. CheckParam ("email", email, 256);
  538. using (DbConnection connection = CreateConnection ()) {
  539. DbCommand command = factory.CreateCommand ();
  540. command.Connection = connection;
  541. command.CommandText = @"aspnet_Membership_GetUserByEmail";
  542. command.CommandType = CommandType.StoredProcedure;
  543. AddParameter (command, "@ApplicationName", ApplicationName);
  544. AddParameter (command, "@Email", email);
  545. DbDataReader reader = command.ExecuteReader ();
  546. string rv = null;
  547. if (reader.Read ())
  548. rv = reader.GetString (0);
  549. reader.Close ();
  550. return rv;
  551. }
  552. }
  553. bool GetBoolConfigValue (NameValueCollection config, string name, bool def)
  554. {
  555. bool rv = def;
  556. string val = config [name];
  557. if (val != null) {
  558. try { rv = Boolean.Parse (val); }
  559. catch (Exception e) {
  560. throw new ProviderException (String.Format ("{0} must be true or false", name), e);
  561. }
  562. }
  563. return rv;
  564. }
  565. int GetIntConfigValue (NameValueCollection config, string name, int def)
  566. {
  567. int rv = def;
  568. string val = config [name];
  569. if (val != null) {
  570. try { rv = Int32.Parse (val); }
  571. catch (Exception e) {
  572. throw new ProviderException (String.Format ("{0} must be an integer", name), e);
  573. }
  574. }
  575. return rv;
  576. }
  577. int GetEnumConfigValue (NameValueCollection config, string name, Type enumType, int def)
  578. {
  579. int rv = def;
  580. string val = config [name];
  581. if (val != null) {
  582. try { rv = (int) Enum.Parse (enumType, val); }
  583. catch (Exception e) {
  584. throw new ProviderException (String.Format ("{0} must be one of the following values: {1}", name, String.Join (",", Enum.GetNames (enumType))), e);
  585. }
  586. }
  587. return rv;
  588. }
  589. string GetStringConfigValue (NameValueCollection config, string name, string def)
  590. {
  591. string rv = def;
  592. string val = config [name];
  593. if (val != null)
  594. rv = val;
  595. return rv;
  596. }
  597. void EmitValidatingPassword (string username, string password, bool isNewUser)
  598. {
  599. ValidatePasswordEventArgs args = new ValidatePasswordEventArgs (username, password, isNewUser);
  600. OnValidatingPassword (args);
  601. /* if we're canceled.. */
  602. if (args.Cancel) {
  603. if (args.FailureInformation == null)
  604. throw new ProviderException ("Password validation canceled");
  605. else
  606. throw args.FailureInformation;
  607. }
  608. }
  609. public override void Initialize (string name, NameValueCollection config)
  610. {
  611. if (config == null)
  612. throw new ArgumentNullException ("config");
  613. base.Initialize (name, config);
  614. applicationName = GetStringConfigValue (config, "applicationName", "/");
  615. enablePasswordReset = GetBoolConfigValue (config, "enablePasswordReset", true);
  616. enablePasswordRetrieval = GetBoolConfigValue (config, "enablePasswordRetrieval", false);
  617. requiresQuestionAndAnswer = GetBoolConfigValue (config, "requiresQuestionAndAnswer", true);
  618. requiresUniqueEmail = GetBoolConfigValue (config, "requiresUniqueEmail", false);
  619. passwordFormat = (MembershipPasswordFormat) GetEnumConfigValue (config, "passwordFormat", typeof (MembershipPasswordFormat),
  620. (int) MembershipPasswordFormat.Hashed);
  621. maxInvalidPasswordAttempts = GetIntConfigValue (config, "maxInvalidPasswordAttempts", 5);
  622. minRequiredPasswordLength = GetIntConfigValue (config, "minRequiredPasswordLength", 7);
  623. minRequiredNonAlphanumericCharacters = GetIntConfigValue (config, "minRequiredNonalphanumericCharacters", 1);
  624. passwordAttemptWindow = GetIntConfigValue (config, "passwordAttemptWindow", 10);
  625. passwordStrengthRegularExpression = GetStringConfigValue (config, "passwordStrengthRegularExpression", "");
  626. MembershipSection section = (MembershipSection) WebConfigurationManager.GetSection ("system.web/membership");
  627. userIsOnlineTimeWindow = section.UserIsOnlineTimeWindow;
  628. /* we can't support password retrieval with hashed passwords */
  629. if (passwordFormat == MembershipPasswordFormat.Hashed && enablePasswordRetrieval)
  630. throw new ProviderException ("password retrieval cannot be used with hashed passwords");
  631. string connectionStringName = config ["connectionStringName"];
  632. if (applicationName.Length > 256)
  633. throw new ProviderException ("The ApplicationName attribute must be 256 characters long or less.");
  634. if (connectionStringName == null || connectionStringName.Length == 0)
  635. throw new ProviderException ("The ConnectionStringName attribute must be present and non-zero length.");
  636. connectionString = WebConfigurationManager.ConnectionStrings [connectionStringName];
  637. factory = connectionString == null || String.IsNullOrEmpty (connectionString.ProviderName) ?
  638. System.Data.SqlClient.SqlClientFactory.Instance :
  639. ProvidersHelper.GetDbProviderFactory (connectionString.ProviderName);
  640. }
  641. public override string ResetPassword (string username, string answer)
  642. {
  643. if (!EnablePasswordReset)
  644. throw new NotSupportedException ("this provider has not been configured to allow the resetting of passwords");
  645. CheckParam ("username", username, 256);
  646. if (RequiresQuestionAndAnswer)
  647. CheckParam ("answer", answer, 128);
  648. using (DbConnection connection = CreateConnection ()) {
  649. PasswordInfo pi = GetPasswordInfo (username);
  650. if (pi == null)
  651. throw new ProviderException (username + "is not found in the membership database");
  652. string newPassword = GeneratePassword ();
  653. EmitValidatingPassword (username, newPassword, false);
  654. string db_password = EncodePassword (newPassword, pi.PasswordFormat, pi.PasswordSalt);
  655. string db_answer = EncodePassword (answer, pi.PasswordFormat, pi.PasswordSalt);
  656. DbCommand command = factory.CreateCommand ();
  657. command.Connection = connection;
  658. command.CommandText = @"aspnet_Membership_ResetPassword";
  659. command.CommandType = CommandType.StoredProcedure;
  660. AddParameter (command, "@ApplicationName", ApplicationName);
  661. AddParameter (command, "@UserName", username);
  662. AddParameter (command, "@NewPassword", db_password);
  663. AddParameter (command, "@MaxInvalidPasswordAttempts", MaxInvalidPasswordAttempts);
  664. AddParameter (command, "@PasswordAttemptWindow", PasswordAttemptWindow);
  665. AddParameter (command, "@PasswordSalt", pi.PasswordSalt);
  666. AddParameter (command, "@CurrentTimeUtc", DateTime.UtcNow);
  667. AddParameter (command, "@PasswordFormat", (int) pi.PasswordFormat);
  668. AddParameter (command, "@PasswordAnswer", db_answer);
  669. DbParameter retValue = AddParameter (command, "@ReturnVal", ParameterDirection.ReturnValue, DbType.Int32, null);
  670. command.ExecuteNonQuery ();
  671. int returnValue = GetReturnValue (retValue);
  672. if (returnValue == 0)
  673. return newPassword;
  674. else if (returnValue == 3)
  675. throw new MembershipPasswordException ("Password Answer is invalid");
  676. else if (returnValue == 99)
  677. throw new MembershipPasswordException ("The user account is currently locked out");
  678. else
  679. throw new ProviderException ("Failed to reset password");
  680. }
  681. }
  682. public override void UpdateUser (MembershipUser user)
  683. {
  684. if (user == null)
  685. throw new ArgumentNullException ("user");
  686. if (user.UserName == null)
  687. throw new ArgumentNullException ("user.UserName");
  688. if (RequiresUniqueEmail && user.Email == null)
  689. throw new ArgumentNullException ("user.Email");
  690. CheckParam ("user.UserName", user.UserName, 256);
  691. if (user.Email.Length > 256 || (RequiresUniqueEmail && user.Email.Length == 0))
  692. throw new ArgumentException ("invalid format for user.Email");
  693. using (DbConnection connection = CreateConnection ()) {
  694. int returnValue = 0;
  695. DbCommand command = factory.CreateCommand ();
  696. command.Connection = connection;
  697. command.CommandText = @"aspnet_Membership_UpdateUser";
  698. command.CommandType = CommandType.StoredProcedure;
  699. AddParameter (command, "@ApplicationName", ApplicationName);
  700. AddParameter (command, "@UserName", user.UserName);
  701. AddParameter (command, "@Email", user.Email == null ? (object) DBNull.Value : (object) user.Email);
  702. AddParameter (command, "@Comment", user.Comment == null ? (object) DBNull.Value : (object) user.Comment);
  703. AddParameter (command, "@IsApproved", user.IsApproved);
  704. AddParameter (command, "@LastLoginDate", DateTime.UtcNow);
  705. AddParameter (command, "@LastActivityDate", DateTime.UtcNow);
  706. AddParameter (command, "@UniqueEmail", RequiresUniqueEmail);
  707. AddParameter (command, "@CurrentTimeUtc", DateTime.UtcNow);
  708. DbParameter retValue = AddParameter (command, "@ReturnVal", ParameterDirection.ReturnValue, DbType.Int32, null);
  709. command.ExecuteNonQuery ();
  710. returnValue = GetReturnValue (retValue);
  711. if (returnValue == 1)
  712. throw new ProviderException ("The UserName property of user was not found in the database.");
  713. if (returnValue == 7)
  714. 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.");
  715. if (returnValue != 0)
  716. throw new ProviderException ("Failed to update user");
  717. }
  718. }
  719. public override bool ValidateUser (string username, string password)
  720. {
  721. if (username.Length == 0)
  722. return false;
  723. CheckParam ("username", username, 256);
  724. EmitValidatingPassword (username, password, false);
  725. PasswordInfo pi = ValidateUsingPassword (username, password);
  726. if (pi != null) {
  727. pi.LastLoginDate = DateTime.UtcNow;
  728. UpdateUserInfo (username, pi, true, true);
  729. return true;
  730. }
  731. return false;
  732. }
  733. public override bool UnlockUser (string username)
  734. {
  735. CheckParam ("username", username, 256);
  736. using (DbConnection connection = CreateConnection ()) {
  737. try {
  738. DbCommand command = factory.CreateCommand ();
  739. command.Connection = connection;
  740. command.CommandText = @"aspnet_Membership_UnlockUser"; ;
  741. command.CommandType = CommandType.StoredProcedure;
  742. AddParameter (command, "@ApplicationName", ApplicationName);
  743. AddParameter (command, "@UserName", username);
  744. DbParameter returnValue = AddParameter (command, "@ReturnVal", ParameterDirection.ReturnValue, DbType.Int32, null);
  745. command.ExecuteNonQuery ();
  746. if (GetReturnValue (returnValue) != 0)
  747. return false;
  748. }
  749. catch (Exception e) {
  750. throw new ProviderException ("Failed to unlock user", e);
  751. }
  752. }
  753. return true;
  754. }
  755. void UpdateUserInfo (string username, PasswordInfo pi, bool isPasswordCorrect, bool updateLoginActivity)
  756. {
  757. CheckParam ("username", username, 256);
  758. using (DbConnection connection = CreateConnection ()) {
  759. try {
  760. DbCommand command = factory.CreateCommand ();
  761. command.Connection = connection;
  762. command.CommandText = @"aspnet_Membership_UpdateUserInfo"; ;
  763. command.CommandType = CommandType.StoredProcedure;
  764. AddParameter (command, "@ApplicationName", ApplicationName);
  765. AddParameter (command, "@UserName", username);
  766. AddParameter (command, "@IsPasswordCorrect", isPasswordCorrect);
  767. AddParameter (command, "@UpdateLastLoginActivityDate", updateLoginActivity);
  768. AddParameter (command, "@MaxInvalidPasswordAttempts", MaxInvalidPasswordAttempts);
  769. AddParameter (command, "@PasswordAttemptWindow", PasswordAttemptWindow);
  770. AddParameter (command, "@CurrentTimeUtc", DateTime.UtcNow);
  771. AddParameter (command, "@LastLoginDate", pi.LastLoginDate);
  772. AddParameter (command, "@LastActivityDate", pi.LastActivityDate);
  773. DbParameter retValue = AddParameter (command, "@ReturnVal", ParameterDirection.ReturnValue, DbType.Int32, null);
  774. command.ExecuteNonQuery ();
  775. int returnValue = GetReturnValue (retValue);
  776. if (returnValue != 0)
  777. return;
  778. }
  779. catch (Exception e) {
  780. throw new ProviderException ("Failed to update Membership table", e);
  781. }
  782. }
  783. }
  784. PasswordInfo ValidateUsingPassword (string username, string password)
  785. {
  786. MembershipUser user = GetUser (username, true);
  787. if (user == null)
  788. return null;
  789. if (!user.IsApproved || user.IsLockedOut)
  790. return null;
  791. PasswordInfo pi = GetPasswordInfo (username);
  792. if (pi == null)
  793. return null;
  794. /* do the actual validation */
  795. string user_password = EncodePassword (password, pi.PasswordFormat, pi.PasswordSalt);
  796. if (user_password != pi.Password) {
  797. UpdateUserInfo (username, pi, false, false);
  798. return null;
  799. }
  800. return pi;
  801. }
  802. private PasswordInfo GetPasswordInfo (string username)
  803. {
  804. using (DbConnection connection = CreateConnection ()) {
  805. DbCommand command = factory.CreateCommand ();
  806. command.Connection = connection;
  807. command.CommandType = CommandType.StoredProcedure;
  808. command.CommandText = @"aspnet_Membership_GetPasswordWithFormat";
  809. AddParameter (command, "@ApplicationName", ApplicationName);
  810. AddParameter (command, "@UserName", username);
  811. AddParameter (command, "@UpdateLastLoginActivityDate", false);
  812. AddParameter (command, "@CurrentTimeUtc", DateTime.Now);
  813. // return value
  814. DbParameter returnValue = AddParameter (command, "@ReturnVal", ParameterDirection.ReturnValue, DbType.Int32, null);
  815. DbDataReader reader = command.ExecuteReader ();
  816. if (!reader.Read ())
  817. return null;
  818. PasswordInfo pi = new PasswordInfo (
  819. reader.GetString (0),
  820. (MembershipPasswordFormat) reader.GetInt32 (1),
  821. reader.GetString (2),
  822. reader.GetInt32 (3),
  823. reader.GetInt32 (4),
  824. reader.GetBoolean (5),
  825. reader.GetDateTime (6),
  826. reader.GetDateTime (7));
  827. return pi;
  828. }
  829. }
  830. private string EncodePassword (string password, MembershipPasswordFormat passwordFormat, string salt)
  831. {
  832. byte [] password_bytes;
  833. byte [] salt_bytes;
  834. switch (passwordFormat) {
  835. case MembershipPasswordFormat.Clear:
  836. return password;
  837. case MembershipPasswordFormat.Hashed:
  838. password_bytes = Encoding.Unicode.GetBytes (password);
  839. salt_bytes = Convert.FromBase64String (salt);
  840. byte [] hashBytes = new byte [salt_bytes.Length + password_bytes.Length];
  841. Buffer.BlockCopy (salt_bytes, 0, hashBytes, 0, salt_bytes.Length);
  842. Buffer.BlockCopy (password_bytes, 0, hashBytes, salt_bytes.Length, password_bytes.Length);
  843. MembershipSection section = (MembershipSection) WebConfigurationManager.GetSection ("system.web/membership");
  844. string alg_type = section.HashAlgorithmType;
  845. if (alg_type == "") {
  846. MachineKeySection keysection = (MachineKeySection) WebConfigurationManager.GetSection ("system.web/machineKey");
  847. alg_type = keysection.Validation.ToString ();
  848. }
  849. using (HashAlgorithm hash = HashAlgorithm.Create (alg_type)) {
  850. hash.TransformFinalBlock (hashBytes, 0, hashBytes.Length);
  851. return Convert.ToBase64String (hash.Hash);
  852. }
  853. case MembershipPasswordFormat.Encrypted:
  854. password_bytes = Encoding.Unicode.GetBytes (password);
  855. salt_bytes = Convert.FromBase64String (salt);
  856. byte [] buf = new byte [password_bytes.Length + salt_bytes.Length];
  857. Array.Copy (salt_bytes, 0, buf, 0, salt_bytes.Length);
  858. Array.Copy (password_bytes, 0, buf, salt_bytes.Length, password_bytes.Length);
  859. return Convert.ToBase64String (EncryptPassword (buf));
  860. default:
  861. /* not reached.. */
  862. return null;
  863. }
  864. }
  865. private string DecodePassword (string password, MembershipPasswordFormat passwordFormat)
  866. {
  867. switch (passwordFormat) {
  868. case MembershipPasswordFormat.Clear:
  869. return password;
  870. case MembershipPasswordFormat.Hashed:
  871. throw new ProviderException ("Hashed passwords cannot be decoded.");
  872. case MembershipPasswordFormat.Encrypted:
  873. return Encoding.Unicode.GetString (DecryptPassword (Convert.FromBase64String (password)));
  874. default:
  875. /* not reached.. */
  876. return null;
  877. }
  878. }
  879. public override string ApplicationName
  880. {
  881. get { return applicationName; }
  882. set { applicationName = value; }
  883. }
  884. public override bool EnablePasswordReset
  885. {
  886. get { return enablePasswordReset; }
  887. }
  888. public override bool EnablePasswordRetrieval
  889. {
  890. get { return enablePasswordRetrieval; }
  891. }
  892. public override MembershipPasswordFormat PasswordFormat
  893. {
  894. get { return passwordFormat; }
  895. }
  896. public override bool RequiresQuestionAndAnswer
  897. {
  898. get { return requiresQuestionAndAnswer; }
  899. }
  900. public override bool RequiresUniqueEmail
  901. {
  902. get { return requiresUniqueEmail; }
  903. }
  904. public override int MaxInvalidPasswordAttempts
  905. {
  906. get { return maxInvalidPasswordAttempts; }
  907. }
  908. public override int MinRequiredNonAlphanumericCharacters
  909. {
  910. get { return minRequiredNonAlphanumericCharacters; }
  911. }
  912. public override int MinRequiredPasswordLength
  913. {
  914. get { return minRequiredPasswordLength; }
  915. }
  916. public override int PasswordAttemptWindow
  917. {
  918. get { return passwordAttemptWindow; }
  919. }
  920. public override string PasswordStrengthRegularExpression
  921. {
  922. get { return passwordStrengthRegularExpression; }
  923. }
  924. [Flags]
  925. private enum DeleteUserTableMask
  926. {
  927. MembershipUsers = 1,
  928. UsersInRoles = 2,
  929. Profiles = 4,
  930. WebPartStateUser = 8
  931. }
  932. private sealed class PasswordInfo
  933. {
  934. private string _password;
  935. private MembershipPasswordFormat _passwordFormat;
  936. private string _passwordSalt;
  937. private int _failedPasswordAttemptCount;
  938. private int _failedPasswordAnswerAttemptCount;
  939. private bool _isApproved;
  940. private DateTime _lastLoginDate;
  941. private DateTime _lastActivityDate;
  942. internal PasswordInfo (
  943. string password,
  944. MembershipPasswordFormat passwordFormat,
  945. string passwordSalt,
  946. int failedPasswordAttemptCount,
  947. int failedPasswordAnswerAttemptCount,
  948. bool isApproved,
  949. DateTime lastLoginDate,
  950. DateTime lastActivityDate)
  951. {
  952. _password = password;
  953. _passwordFormat = passwordFormat;
  954. _passwordSalt = passwordSalt;
  955. _failedPasswordAttemptCount = failedPasswordAttemptCount;
  956. _failedPasswordAnswerAttemptCount = failedPasswordAnswerAttemptCount;
  957. _isApproved = isApproved;
  958. _lastLoginDate = lastLoginDate;
  959. _lastActivityDate = lastActivityDate;
  960. }
  961. public string Password
  962. {
  963. get { return _password; }
  964. set { _password = value; }
  965. }
  966. public MembershipPasswordFormat PasswordFormat
  967. {
  968. get { return _passwordFormat; }
  969. set { _passwordFormat = value; }
  970. }
  971. public string PasswordSalt
  972. {
  973. get { return _passwordSalt; }
  974. set { _passwordSalt = value; }
  975. }
  976. public int FailedPasswordAttemptCount
  977. {
  978. get { return _failedPasswordAttemptCount; }
  979. set { _failedPasswordAttemptCount = value; }
  980. }
  981. public int FailedPasswordAnswerAttemptCount
  982. {
  983. get { return _failedPasswordAnswerAttemptCount; }
  984. set { _failedPasswordAnswerAttemptCount = value; }
  985. }
  986. public bool IsApproved
  987. {
  988. get { return _isApproved; }
  989. set { _isApproved = value; }
  990. }
  991. public DateTime LastLoginDate
  992. {
  993. get { return _lastLoginDate; }
  994. set { _lastLoginDate = value; }
  995. }
  996. public DateTime LastActivityDate
  997. {
  998. get { return _lastActivityDate; }
  999. set { _lastActivityDate = value; }
  1000. }
  1001. }
  1002. }
  1003. }
  1004. #endif