Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.Services.Authentication Prototype/Service/Provider/HeuristicLabMembershipProvider.cs @ 4002

Last change on this file since 4002 was 4002, checked in by bfarka, 14 years ago

made struture changes in persistence classes and provider

File size: 16.6 KB
Line 
1using System;
2using System.Collections.Specialized;
3using System.Configuration;
4using System.Configuration.Provider;
5using System.IO;
6using System.Linq;
7using System.Security.Cryptography;
8using System.Text;
9using System.Web.Configuration;
10using System.Web.Security;
11using Persistence;
12
13
14namespace Service.Provider {
15  class HeuristicLabMembershipProvider : MembershipProvider {
16
17    #region variables
18
19    private string pApplicationName;
20    private bool pEnablePasswordReset;
21    private bool pEnablePasswordRetrieval;
22    private bool pRequiresQuestionAndAnswer;
23    private bool pRequiresUniqueEmail;
24    private int pMaxInvalidPasswordAttempts;
25    private int pPasswordAttemptWindow;
26    private int pMinRequiredPasswordLength;
27    private MembershipPasswordFormat pPasswordFormat = MembershipPasswordFormat.Clear;
28
29    #endregion
30
31    #region properties
32
33    public override string ApplicationName {
34      get { return pApplicationName; }
35      set { pApplicationName = value; }
36    }
37
38    public override bool EnablePasswordReset {
39      get { return pEnablePasswordReset; }
40    }
41
42    public override bool EnablePasswordRetrieval {
43      get { return pEnablePasswordRetrieval; }
44    }
45
46    public override int MaxInvalidPasswordAttempts {
47      get { return pMaxInvalidPasswordAttempts; }
48    }
49
50    public override int MinRequiredNonAlphanumericCharacters {
51      get { return 0; }
52    }
53
54    public override int MinRequiredPasswordLength {
55      get { return pMinRequiredPasswordLength; }
56    }
57
58    public override int PasswordAttemptWindow {
59      get { return pPasswordAttemptWindow; }
60    }
61
62    public override MembershipPasswordFormat PasswordFormat {
63      get { return pPasswordFormat; }
64    }
65
66    public override string PasswordStrengthRegularExpression {
67      get { return string.Empty; }
68    }
69
70    public override bool RequiresQuestionAndAnswer {
71      get { return pRequiresQuestionAndAnswer; }
72    }
73
74    public override bool RequiresUniqueEmail {
75      get { return pRequiresUniqueEmail; }
76    }
77
78    #endregion
79
80    public override void Initialize(string name, NameValueCollection config) {
81      //
82      // Initialize values from web.config.
83      //
84
85      if (config == null)
86        throw new ArgumentNullException("config");
87
88      if (string.IsNullOrEmpty(name) || name.Length == 0)
89        name = "HeuristicLabMembershipProvider";
90
91      if (String.IsNullOrEmpty(config["description"])) {
92        config.Remove("description");
93        config.Add("description", "Heuristic Lab Membership provider");
94      }
95
96      // Initialize the abstract base class.
97      base.Initialize(name, config);
98
99      pApplicationName = GetConfigValue(config["applicationName"], System.Web.Hosting.HostingEnvironment.ApplicationVirtualPath);
100      pMaxInvalidPasswordAttempts = Convert.ToInt32(GetConfigValue(config["maxInvalidPasswordAttempts"], "5"));
101      pPasswordAttemptWindow = Convert.ToInt32(GetConfigValue(config["passwordAttemptWindow"], "10"));
102      pMinRequiredPasswordLength = Convert.ToInt32(GetConfigValue(config["minRequiredPasswordLength"], "7"));
103      pEnablePasswordReset = Convert.ToBoolean(GetConfigValue(config["enablePasswordReset"], "true"));
104      pEnablePasswordRetrieval = Convert.ToBoolean(GetConfigValue(config["enablePasswordRetrieval"], "true"));
105      pRequiresQuestionAndAnswer = Convert.ToBoolean(GetConfigValue(config["requiresQuestionAndAnswer"], "false"));
106      pRequiresUniqueEmail = Convert.ToBoolean(GetConfigValue(config["requiresUniqueEmail"], "true"));
107
108      string tempFormat = config["passwordFormat"];
109      if (tempFormat == null) {
110        tempFormat = "Clear";
111      }
112
113      switch (tempFormat) {
114        case "Hashed":
115          pPasswordFormat = MembershipPasswordFormat.Hashed;
116          break;
117        case "Encrypted":
118          pPasswordFormat = MembershipPasswordFormat.Encrypted;
119          break;
120        case "Clear":
121          pPasswordFormat = MembershipPasswordFormat.Clear;
122          break;
123        default:
124          throw new ProviderException("Password format not supported.");
125      }
126    }
127
128
129
130    public override bool ChangePassword(string username, string oldPassword, string newPassword) {
131      using (DataClassesDataContext db = DatabaseUtil.createDataClassesDataContext()) {
132        // check database connection
133        if (db == null) {
134          return false;
135        }
136        try {
137          // try to get user
138          HeuristicLabUser u = db.HeuristicLabUsers.Single(x => x.UserName == username);
139
140          if (u.Password == EncodePassword(oldPassword) && newPassword.Length > 0) {
141            u.Password = EncodePassword(newPassword);
142            db.SubmitChanges();
143            return true;
144          }
145          return false;
146         
147         
148        }
149        catch (Exception) {
150          return false;
151        }
152      }
153    }
154
155    public override bool ChangePasswordQuestionAndAnswer(string username, string password, string newPasswordQuestion, string newPasswordAnswer) {
156      using (DataClassesDataContext db = DatabaseUtil.createDataClassesDataContext()) {
157
158        if (db.HeuristicLabUsers.Count(x => x.UserName == username) > 0 && newPasswordQuestion.Length > 0 && newPasswordAnswer.Length > 0) {
159          HeuristicLabUser u = db.HeuristicLabUsers.Single(x => x.UserName == username);
160          u.PasswordAnswer = newPasswordAnswer;
161          u.PasswordQuestion = newPasswordQuestion;
162          db.SubmitChanges();
163          return true;
164        }
165        return false;
166      }
167    }
168
169    public override MembershipUser CreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status) {
170      using (DataClassesDataContext db = DatabaseUtil.createDataClassesDataContext()) {
171        // check database connection
172        if (db == null) {
173          status = MembershipCreateStatus.ProviderError;
174          return null;
175        }
176        try {
177          // check for duplicate entries
178          if (db.HeuristicLabUsers.Count(x => x.UserName == username) > 0) {
179            status = MembershipCreateStatus.DuplicateUserName;
180            return null;
181          }
182          if (db.HeuristicLabUsers.Count(x => x.Email == email) > 0) {
183            status = MembershipCreateStatus.DuplicateEmail;
184            return null;
185          }
186
187          // create new user
188          HeuristicLabUser u = new HeuristicLabUser(username, email, passwordQuestion, "");
189          password = EncodePassword(password);
190          u.Password = password;
191          u.PasswordAnswer = passwordAnswer;
192          u.PasswordQuestion = passwordQuestion;
193          // save user into database
194          db.HeuristicLabUsers.InsertOnSubmit(u);
195          db.SubmitChanges();
196
197          // success
198          status = MembershipCreateStatus.Success;
199          return u.getMembershipUser(this.Name);
200        }
201        catch (Exception) {
202          // error
203          status = MembershipCreateStatus.ProviderError;
204          return null;
205        }
206      }
207    }
208
209    public override bool DeleteUser(string username, bool deleteAllRelatedData) {
210      using (DataClassesDataContext db = DatabaseUtil.createDataClassesDataContext()) {
211        // check database connection
212        if (db == null) {
213          return false;
214        }
215        try {
216          // try to get user
217          HeuristicLabUser u =
218            db.HeuristicLabUsers.Single<HeuristicLabUser>(x => x.UserName == username);
219
220          // optionally delete related data
221          if (deleteAllRelatedData) {
222            db.HeuristicLabUserRole.DeleteAllOnSubmit<HeuristicLabUserRole>(u.HeuristicLabUserRoles);
223          }
224
225          // delete user
226          db.HeuristicLabUsers.DeleteOnSubmit(u);
227          db.SubmitChanges();
228          return true;
229        }
230        catch (Exception) {
231          return false;
232        }
233      }
234    }
235
236
237
238    public override MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize, out int totalRecords) {
239      throw new NotImplementedException();
240    }
241
242    public override MembershipUserCollection FindUsersByName(string usernameToMatch, int pageIndex, int pageSize, out int totalRecords) {
243      throw new NotImplementedException();
244    }
245
246    // not for production use - fab and dkhan are currently working on that
247    public override MembershipUserCollection GetAllUsers(int pageIndex, int pageSize, out int totalRecords) {
248      totalRecords = 0;
249      using (DataClassesDataContext db = DatabaseUtil.createDataClassesDataContext()) {
250        if (db == null) {
251          totalRecords = 0;
252          return new MembershipUserCollection();
253        }
254
255        // bail out if there are no records
256        if (0 == (totalRecords = db.HeuristicLabUsers.Count<HeuristicLabUser>())) return new MembershipUserCollection();
257
258        MembershipUserCollection userCollection = new MembershipUserCollection();
259        int skip = (pageIndex == 0) ? 0 : (pageIndex * pageSize) - 1;
260
261        var users = from u in db.HeuristicLabUsers select u;
262
263        foreach (HeuristicLabUser u in users) {
264
265          // this leads to a npe
266          if (u != null) {
267            userCollection.Add(u.getMembershipUser(this.Name));
268          }
269        }
270        return userCollection;
271      }
272    }
273
274    public override int GetNumberOfUsersOnline() {
275      throw new NotImplementedException();
276    }
277
278    public override string GetPassword(string username, string answer) {
279
280      throw new NotImplementedException();
281    }
282
283    public override MembershipUser GetUser(string username, bool userIsOnline) {
284      throw new NotImplementedException();
285    }
286
287    public override MembershipUser GetUser(object providerUserKey, bool userIsOnline) {
288      throw new NotImplementedException();
289    }
290
291    public override string GetUserNameByEmail(string email) {
292      throw new NotImplementedException();
293    }
294
295
296
297    public override string ResetPassword(string username, string answer) {
298      throw new NotImplementedException();
299    }
300
301    public bool LockUser(string userName)
302    {
303        using (DataClassesDataContext db = DatabaseUtil.createDataClassesDataContext())
304        {
305            // check database connection
306            if (db == null)
307            {
308                return false;
309            }
310            try
311            {
312                // try to get user
313                HeuristicLabUser u =
314                  db.HeuristicLabUsers.Single<HeuristicLabUser>(x => x.UserName == userName);
315
316                // unlock user
317                u.Locked = true;
318                db.SubmitChanges();
319                return true;
320            }
321            catch (Exception)
322            {
323                return false;
324            }
325        }
326    }
327
328    public override bool UnlockUser(string userName)
329    {
330        using (DataClassesDataContext db = DatabaseUtil.createDataClassesDataContext())
331        {
332            // check database connection
333            if (db == null)
334            {
335                return false;
336            }
337            try
338            {
339                // try to get user
340                HeuristicLabUser u =
341                  db.HeuristicLabUsers.Single<HeuristicLabUser>(x => x.UserName == userName);
342
343                // unlock user
344                u.Locked = false;
345                db.SubmitChanges();
346                return true;
347            }
348            catch (Exception)
349            {
350                return false;
351            }
352        }
353    }
354
355    public override void UpdateUser(MembershipUser user) {
356      throw new NotImplementedException();
357    }
358    /// <summary>
359    /// Validates a user
360    /// </summary>
361    /// <param name="username"></param>
362    /// <param name="password"></param>
363    /// <returns></returns>
364    public override bool ValidateUser(string username, string password) {
365      bool isValid = false;
366      using (DataClassesDataContext db = DatabaseUtil.createDataClassesDataContext()) {
367        if (db == null) {
368          return false;
369        }
370        HeuristicLabUser u = db.HeuristicLabUsers.Single(x => x.UserName == username);
371        isValid = CheckPassword(password, u.Password);
372      }
373      return isValid;
374    }
375
376    /// <summary>
377    /// compaiers to passwords
378    /// </summary>
379    /// <param name="password"></param>
380    /// <param name="dbpassword"></param>
381    /// <returns></returns>
382    private bool CheckPassword(string password, string dbpassword) {
383      string pass1 = password;
384      string pass2 = dbpassword;
385
386      switch (PasswordFormat) {
387        case MembershipPasswordFormat.Encrypted:
388          pass2 = DecodePassword(dbpassword);
389          break;
390        case MembershipPasswordFormat.Hashed:
391          pass1 = EncodePassword(password);
392          break;
393        default:
394          break;
395      }
396
397      if (pass1 == pass2) {
398        return true;
399      }
400
401      return false;
402    }
403
404
405    /// <summary>
406    /// Encodes a password
407    /// </summary>
408    /// <param name="password"></param>
409    /// <returns></returns>
410    private string EncodePassword(string password) {
411      string encodedPassword = password;
412
413      switch (PasswordFormat) {
414        case MembershipPasswordFormat.Clear:
415          break;
416        case MembershipPasswordFormat.Encrypted:
417          encodedPassword =
418            Convert.ToBase64String(EncryptPassword(Encoding.Unicode.GetBytes(password)));
419          break;
420        case MembershipPasswordFormat.Hashed:
421          SHA512 sha512 = SHA512.Create();
422          ASCIIEncoding encoder = new ASCIIEncoding();
423          byte[] combined = encoder.GetBytes(password);
424          sha512.ComputeHash(combined);
425          encodedPassword = Convert.ToBase64String(sha512.Hash);
426          break;
427        default:
428          throw new ProviderException("Unsupported password format.");
429      }
430
431      return encodedPassword;
432    }
433
434    private readonly byte[] _rgbKey = new byte[]
435                           {
436                             182, 140, 37, 101, 52, 157, 80, 17, 65, 35, 130, 208, 101, 68, 161, 45, 197, 102, 112, 190,
437                             187, 177, 37, 76, 63, 38, 190, 117, 247, 122, 94, 17
438                           };
439    private readonly byte[] _rgbIv = new byte[] { 60, 121, 178, 142, 50, 160, 226, 84, 41, 66, 158, 180, 26, 232, 42, 113 };
440
441    protected override byte[] EncryptPassword(byte[] password) {
442      SymmetricAlgorithm sa = Aes.Create();
443      MemoryStream msEncrypt = new MemoryStream();
444      CryptoStream csEncrypt = new CryptoStream(msEncrypt, sa.CreateEncryptor(_rgbKey, _rgbIv), CryptoStreamMode.Write);
445      csEncrypt.Write(password, 0, password.Length);
446      csEncrypt.Close();
447      byte[] encryptedTextBytes = msEncrypt.ToArray();
448      msEncrypt.Close();
449      return encryptedTextBytes;
450    }
451
452    protected override byte[] DecryptPassword(byte[] encodedPassword) {
453      SymmetricAlgorithm sa = Aes.Create();
454      MemoryStream msDecrypt = new MemoryStream(encodedPassword);
455      CryptoStream csDecrypt = new CryptoStream(msDecrypt, sa.CreateDecryptor(_rgbKey, _rgbIv), CryptoStreamMode.Read);
456      byte[] decryptedTextBytes = new Byte[encodedPassword.Length];
457      csDecrypt.Read(decryptedTextBytes, 0, encodedPassword.Length);
458      csDecrypt.Close();
459      msDecrypt.Close();
460      return decryptedTextBytes;
461    }
462
463    /// <summary>
464    /// Decodes a encoded Password
465    /// </summary>
466    /// <param name="encodedPassword"></param>
467    /// <returns></returns>
468    private string DecodePassword(string encodedPassword) {
469      string password = encodedPassword;
470
471      switch (PasswordFormat) {
472        case MembershipPasswordFormat.Clear:
473          break;
474        case MembershipPasswordFormat.Encrypted:
475          password =
476            Encoding.Unicode.GetString(DecryptPassword(Convert.FromBase64String(password))).TrimEnd('\0');
477
478
479          break;
480        case MembershipPasswordFormat.Hashed:
481          throw new ProviderException("Cannot unencode a hashed password.");
482        default:
483          throw new ProviderException("Unsupported password format.");
484      }
485
486      return password;
487    }
488
489    /// <summary>
490    /// returns the configuration string, if the value is null or empty the default value is returned
491    /// </summary>
492    /// <param name="configValue"></param>
493    /// <param name="defaultValue"></param>
494    /// <returns></returns>
495    private string GetConfigValue(string configValue, string defaultValue) {
496      if (String.IsNullOrEmpty(configValue))
497        return defaultValue;
498
499      return configValue;
500    }
501  }
502}
Note: See TracBrowser for help on using the repository browser.