2012-06-22 82 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