PageRenderTime 25ms CodeModel.GetById 7ms RepoModel.GetById 0ms app.codeStats 0ms

/Crab.Web.Security/WCFTenantMembershipProvider.cs

#
C# | 357 lines | 307 code | 44 blank | 6 comment | 39 complexity | 8cd3b4228c8c5d6faa97e65997388b28 MD5 | raw file
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using System.Text.RegularExpressions;
  5. using System.Web;
  6. using System.Web.Util;
  7. using System.Web.Security;
  8. using System.Diagnostics;
  9. using System.Runtime.InteropServices;
  10. using System.Configuration.Provider;
  11. using System.Reflection;
  12. using System.Security.Principal;
  13. using Crab.Services.Proxy;
  14. using Crab.Runtime.Contract;
  15. namespace Crab.Web.Security
  16. {
  17. /// <summary>
  18. /// Manages storage of tenant membership information for an ASP.NET application in
  19. /// Active Directory Application Mode service.
  20. /// </summary>
  21. public class WCFTenantMembershipProvider : MembershipProvider
  22. {
  23. private string _applicationName = "/";
  24. public WCFTenantMembershipProvider()
  25. {
  26. }
  27. public override string ApplicationName
  28. {
  29. get
  30. {
  31. return this._applicationName;
  32. }
  33. set
  34. {
  35. this._applicationName = value;
  36. }
  37. }
  38. public override bool EnablePasswordReset
  39. {
  40. get { return WCFMembershipConfigurationManager.EnablePasswordReset; }
  41. }
  42. public override bool EnablePasswordRetrieval
  43. {
  44. get { throw new NotSupportedException();}
  45. }
  46. public override int MaxInvalidPasswordAttempts
  47. {
  48. get { throw new NotImplementedException(); }
  49. }
  50. public override int MinRequiredNonAlphanumericCharacters
  51. {
  52. get { return WCFMembershipConfigurationManager.MinRequiredNonAlphanumericCharacters; }
  53. }
  54. public override int MinRequiredPasswordLength
  55. {
  56. get { return WCFMembershipConfigurationManager.MinRequiredPasswordLength; }
  57. }
  58. public override int PasswordAttemptWindow
  59. {
  60. get { throw new NotImplementedException(); }
  61. }
  62. public override MembershipPasswordFormat PasswordFormat
  63. {
  64. get { throw new NotImplementedException(); }
  65. }
  66. public override string PasswordStrengthRegularExpression
  67. {
  68. get { return WCFMembershipConfigurationManager.PasswordStrengthRegularExpression; }
  69. }
  70. public override bool RequiresQuestionAndAnswer
  71. {
  72. get { return false; }
  73. }
  74. public override bool RequiresUniqueEmail
  75. {
  76. get { throw new NotSupportedException(); }
  77. }
  78. public override bool ChangePasswordQuestionAndAnswer(string username, string password, string newPasswordQuestion, string newPasswordAnswer)
  79. {
  80. throw new NotSupportedException();
  81. }
  82. public override string GetPassword(string username, string answer)
  83. {
  84. throw new NotSupportedException();
  85. }
  86. public override string GetUserNameByEmail(string email)
  87. {
  88. throw new NotImplementedException();
  89. }
  90. public override string ResetPassword(string username, string answer)
  91. {
  92. throw new NotImplementedException();
  93. }
  94. public override bool UnlockUser(string userName)
  95. {
  96. throw new NotImplementedException();
  97. }
  98. public override void UpdateUser(MembershipUser user)
  99. {
  100. throw new NotImplementedException();
  101. }
  102. public override MembershipUser CreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status)
  103. {
  104. status = MembershipCreateStatus.Success;
  105. string tenantName;
  106. string tenantUsername;
  107. if(string.IsNullOrEmpty(username))
  108. {
  109. status = MembershipCreateStatus.InvalidUserName;
  110. return null;
  111. }
  112. if(!Upn.TryParse(username, out tenantName, out tenantUsername))
  113. {
  114. status = MembershipCreateStatus.InvalidUserName;
  115. return null;
  116. }
  117. if (string.IsNullOrEmpty(email))
  118. {
  119. status = MembershipCreateStatus.InvalidEmail;
  120. return null;
  121. }
  122. if (string.IsNullOrEmpty(password) || password.Length < MinRequiredPasswordLength)
  123. {
  124. status = MembershipCreateStatus.InvalidPassword;
  125. return null;
  126. }
  127. int i = 0;
  128. for (int j = 0; j < password.Length; j++)
  129. {
  130. if (!char.IsLetterOrDigit(password, j))
  131. {
  132. i++;
  133. }
  134. }
  135. if (i < MinRequiredNonAlphanumericCharacters)
  136. {
  137. status = MembershipCreateStatus.InvalidPassword;
  138. return null;
  139. }
  140. if ((PasswordStrengthRegularExpression.Length > 0) && !Regex.IsMatch(password, PasswordStrengthRegularExpression))
  141. {
  142. status = MembershipCreateStatus.InvalidPassword;
  143. return null;
  144. }
  145. ValidatePasswordEventArgs args = new ValidatePasswordEventArgs(username, password, true);
  146. base.OnValidatingPassword(args);
  147. if (args.Cancel)
  148. {
  149. status = MembershipCreateStatus.InvalidPassword;
  150. return null;
  151. }
  152. try
  153. {
  154. if (AuthenticationProxy.UserExists(tenantName, tenantUsername))
  155. {
  156. status = MembershipCreateStatus.DuplicateUserName;
  157. return null;
  158. }
  159. AuthenticationProxy.CreateUser(tenantName, tenantUsername, password, email);
  160. }
  161. catch (Exception ex)
  162. {
  163. throw new ProviderException(ex.Message, ex);
  164. }
  165. return GetUser(username, false);
  166. }
  167. public override MembershipUser GetUser(string username, bool userIsOnline)
  168. {
  169. string tenantName;
  170. string tenantUsername;
  171. if (!Upn.TryParse(username, out tenantName, out tenantUsername))
  172. {
  173. throw new ArgumentException(string.Format("The username {0} is invalid!", username));
  174. }
  175. AdamUser adamUser = AuthenticationProxy.GetAdamUser(tenantName, tenantUsername);
  176. if (adamUser == null)
  177. return null;
  178. object providerUserKey = new SecurityIdentifier(adamUser.Sid, 0);
  179. return new ActiveDirectoryMembershipUser(this.Name, adamUser.PrincipleName, providerUserKey, adamUser.Email, string.Empty, string.Empty
  180. , true, false, DateTime.Now, DateTime.Now, DateTime.Now, DateTime.Now, DateTime.Now);
  181. }
  182. public override MembershipUser GetUser(object providerUserKey, bool userIsOnline)
  183. {
  184. throw new NotImplementedException();
  185. }
  186. public override bool ValidateUser(string username, string password)
  187. {
  188. string tenantName;
  189. string tenantUsername;
  190. if (!Upn.TryParse(username, out tenantName, out tenantUsername))
  191. return false;
  192. return AuthenticationProxy.ValidateUser(tenantName, tenantUsername, password);
  193. }
  194. public override bool DeleteUser(string username, bool deleteAllRelatedData)
  195. {
  196. if (string.IsNullOrEmpty(username))
  197. {
  198. throw new ArgumentNullException("username");
  199. }
  200. string tenantName;
  201. string tenantUsername;
  202. if (!Upn.TryParse(username, out tenantName, out tenantUsername))
  203. return false; //invalid username format
  204. try
  205. {
  206. if (!AuthenticationProxy.UserExists(tenantName, tenantUsername))
  207. return false; //not exists
  208. AuthenticationProxy.DeleteUser(tenantName, tenantUsername);
  209. }
  210. catch(Exception ex)
  211. {
  212. throw new ProviderException(ex.Message, ex);
  213. }
  214. return true;
  215. }
  216. public override bool ChangePassword(string username, string oldPassword, string newPassword)
  217. {
  218. if (string.IsNullOrEmpty(username))
  219. {
  220. throw new ArgumentNullException("username");
  221. }
  222. string tenantName;
  223. string tenantUsername;
  224. if (!Upn.TryParse(username, out tenantName, out tenantUsername))
  225. return false;
  226. CheckPassword(oldPassword, MinRequiredPasswordLength, "oldPassword");
  227. CheckPassword(oldPassword, MinRequiredPasswordLength, "newPassword");
  228. if (newPassword.Length < this.MinRequiredPasswordLength)
  229. {
  230. throw new ArgumentException(string.Format("The length of the passowrd {0} must not be shorter than {1} characters!", "newPassword", MinRequiredPasswordLength));
  231. }
  232. int num1 = 0;
  233. for (int num2 = 0; num2 < newPassword.Length; num2++)
  234. {
  235. if (!char.IsLetterOrDigit(newPassword, num2))
  236. {
  237. num1++;
  238. }
  239. }
  240. if (num1 < this.MinRequiredNonAlphanumericCharacters)
  241. {
  242. throw new ArgumentException(string.Format("Non alpha numeric characters of {0} must be more than {1}", "newPassword", MinRequiredNonAlphanumericCharacters));
  243. }
  244. if ((this.PasswordStrengthRegularExpression.Length > 0) && !Regex.IsMatch(newPassword, this.PasswordStrengthRegularExpression))
  245. {
  246. throw new ArgumentException(string.Format("The format of the password {0} is not correct!", "newPassword"));
  247. }
  248. AuthenticationProxy.ChangePassword(tenantName, tenantUsername, oldPassword, newPassword);
  249. return true;
  250. }
  251. protected virtual void CheckPassword(string password, int maxSize, string paramName)
  252. {
  253. if (password == null)
  254. {
  255. throw new ArgumentNullException(paramName);
  256. }
  257. if (password.Trim().Length < 1)
  258. {
  259. throw new ArgumentException(string.Format("The {0} can not be empty", paramName), paramName);
  260. }
  261. if ((maxSize > 0) && (password.Length > maxSize))
  262. {
  263. throw new ArgumentException(string.Format("The length of {0} can not exceed {1}", paramName, maxSize.ToString()), paramName);
  264. }
  265. }
  266. public override MembershipUserCollection FindUsersByName(string usernameToMatch, int pageIndex, int pageSize, out int totalRecords)
  267. {
  268. //extract tenant name from the current user upn
  269. string tenantName;
  270. string username;
  271. Upn.TryParse(HttpContext.Current.User.Identity.Name, out tenantName, out username);
  272. MembershipUserCollection collection = new MembershipUserCollection();
  273. string[] usernames = AuthenticationProxy.FindUsers(tenantName, usernameToMatch);
  274. totalRecords = usernames.Length;
  275. int start = pageIndex * pageSize;
  276. if (start >= 0 && start < totalRecords)
  277. {
  278. for(int i=start; i<totalRecords&&i<start+pageSize; i++)
  279. {
  280. collection.Add(System.Web.Security.Membership.GetUser((new Upn(tenantName, usernames[i])).ToString()));
  281. }
  282. }
  283. return collection;
  284. }
  285. public override MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize, out int totalRecords)
  286. {
  287. throw new NotImplementedException();
  288. }
  289. public override MembershipUserCollection GetAllUsers(int pageIndex, int pageSize, out int totalRecords)
  290. {
  291. //extract tenant name from the current user upn
  292. string tenantName;
  293. string username;
  294. Upn.TryParse(HttpContext.Current.User.Identity.Name, out tenantName, out username);
  295. MembershipUserCollection collection = new MembershipUserCollection();
  296. string[] usernames = AuthenticationProxy.GetUsers(tenantName);
  297. totalRecords = usernames.Length;
  298. int start = pageIndex * pageSize;
  299. if (start >= 0 && start < totalRecords)
  300. {
  301. for (int i = start; i < totalRecords && i < start + pageSize; i++)
  302. {
  303. collection.Add(System.Web.Security.Membership.GetUser((new Upn(tenantName, usernames[i])).ToString()));
  304. }
  305. }
  306. return collection;
  307. }
  308. public override int GetNumberOfUsersOnline()
  309. {
  310. throw new NotImplementedException();
  311. }
  312. }
  313. }