2012-06-22 79 views
5

我是一個CS專業,我剛剛完成了設計一個ASP.net站點,併爲該網站我需要一個登錄身份驗證系統......我不想使用SQLMembershipProvider,因爲我真的很想學習如何使自己成爲一個...反正這就是我想出的,我想知道是否有人可以給我一些反饋,提示或建議。ASP.net身份驗證

由於提前

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 
using System.Web.Security; 
using System.Security.Cryptography; 

/// <summary> 
/// Summary description for PwEncrypt 
/// </summary> 
public class PwEncrypt 
{ 
    public const int DefaultSaltSize = 5; 

    private static string CreateSalt() 
    { 
     RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider(); 
     byte[] buffer = new byte[DefaultSaltSize]; 
     rng.GetBytes(buffer); 
     return Convert.ToBase64String(buffer); 
    } 

    public static string CreateHash(string password, out string salt) 
    { 
     salt = CreateSalt(); 
     string saltAndPassword = String.Concat(password, salt); 
     string hashedPassword = FormsAuthentication.HashPasswordForStoringInConfigFile(saltAndPassword, "SHA1"); 
     hashedPassword = string.Concat(hashedPassword, salt); 
     return hashedPassword; 
    } 
     public static string CreateHashAndGetSalt(string password, string salt) 
    { 

     string saltAndPassword = String.Concat(password, salt); 
     string hashedPassword = FormsAuthentication.HashPasswordForStoringInConfigFile(saltAndPassword, "SHA1"); 
     hashedPassword = string.Concat(hashedPassword, salt); 
     return hashedPassword; 
    } 

    public static bool comparePassword(string insertedPassword, string incUserName, out string newEncryptedPassword, out string originalPassword) 
    { 
     databaseInteraction DBI = new databaseInteraction(); 
     string actualPassword =""; 
     string salt = ""; 


     DBI.getSaltandPassword(incUserName, out salt, out actualPassword); 
     string hashedIncPassword = PwEncrypt.CreateHashAndGetSalt(insertedPassword, salt); 
     // hashedIncPassword = string.Concat(hashedIncPassword, salt);  
     newEncryptedPassword = hashedIncPassword; 
     originalPassword = actualPassword; 
     if (newEncryptedPassword == originalPassword) 
     { 

      return true; 
     } 

     else { return false; } 

    } 
+0

如果您想創建自定義成員資格提供程序,您首先必須從MemberShipProvider繼承。如果你有一點谷歌,這是很好的記錄。 –

+2

不要試圖推出自己的自定義身份驗證和會話管理方案,或建立自己的控件,除非您沒有別的選擇。我只想做,不符合資格。一個有趣的閱讀:http://www.troyhunt.com/2010/07/owasp-top-10-for-net-developers-part-3.html –

+0

@ChristopheGeers Exactly ...你自己做這件事很麻煩,內置的MembershipProviders工作得很好,它們只能被配置爲這樣做。 – sinni800

回答

1

假設我們有一個表像這樣

enter image description here

帳戶然後您可以創建一個返回帳戶對象

private static Account GetByName(string accountName, bool activatedOnly = false) 
{ 
    using (var context = new DBEntities()) 
    { 
     return context.Accounts.FirstOrDefault(s => 
      s.AccountName == accountName && 
      s.IsApproved == activatedOnly); 
    } 
} 

public static Account Get(string accountName, string password) 
{ 
    var account = GetByName(accountName, true); 
    if (account != null) 
     if (!Cryptographer.IsValidPassword(password, 
              account.PasswordSalt, 
              account.PasswordKey)) 
      return null; 
    return account; 
} 

一些輔助類我正在使用EntityFramework,但這裏並不重要。主要想法是證明您不需要獲得所有帳戶列表(特別是如果您有大量用戶)。
Cryptographer類是什麼樣子

public class Cryptographer 
{ 
    private const int keyByteLength = 20; 
    public static void Encrypt(string password, 
           out byte[] salt, 
           out byte[] key) 
    { 
     using (var deriveBytes = new Rfc2898DeriveBytes(password, 
                 keyByteLength)) 
     { 
      salt = deriveBytes.Salt; 
      key = deriveBytes.GetBytes(keyByteLength); 
     } 
    } 
    public static bool IsValidPassword(string password, 
             byte[] salt, 
             byte[] key) 
    { 
     using (var deriveBytes = new Rfc2898DeriveBytes(password, salt)) 
     { 
      byte[] newKey = deriveBytes.GetBytes(keyByteLength); 
      return newKey.SequenceEqual(key); 
     } 
    } 
} 

五言,你可以實現自己的算法。

+0

謝謝,這正是我正在尋找的反饋類型...關於使用Rfc2898DeriveBytes vs RNGCryptoServiceProvider和FormsAuthentication.HashPasswordForStoringInConfigFile ...哪一個具有更強大的散列算法?至於獲取用戶的整個列表,其他方法實際上處理讓特定用戶檢查密碼,incUserID限制密碼檢查只有一個,所以我的意思是它選擇對整個數據庫只有1回報,但EntityFramework會做同樣的事情嗎? – user1474120

+0

@ user1474120 - 您將遇到的主要問題是寫入安全的SQL查詢。根據您自己的代碼,您不使用安全密碼架構這是一個問題,但以安全的方式獲取用戶和密碼是一個更大的問題。 –

+0

@ user1474120,看看[this](http://security.stackexchange.com/questions/2051/is-pbkdf2-based-system-cryptology-rfc2898derivebytes-better-for-unicode-pass) – Shymep