2012-06-22 4 views
5

Im un CS majeur et je viens de finir de concevoir un site ASP.net, et pour le site j'avais besoin d'un système d'authentification de connexion ... Je ne voulais pas utiliser SQLMembershipProvider car je voulais vraiment apprendre comment en fabriquer un seul ... Quoi qu'il en soit, c'est ce que j'ai imaginé, et je me demandais si quelqu'un pouvait me donner des commentaires, des conseils ou des conseils.Authentification ASP.net

Merci à l'avance

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

Si vous souhaitez créer un fournisseur d'appartenances personnalisé, vous devez d'abord hériter de MemberShipProvider. Et c'est assez bien documenté si vous google un peu. –

+2

N'essayez pas de lancer vos propres schémas d'authentification et de gestion de session personnalisés ou de créer vos propres contrôles à moins que vous n'ayez pas vraiment d'autre choix. Je veux juste le faire, ne me qualifie pas. Une lecture intéressante: http://www.troyhunt.com/2010/07/owasp-top-10-for-net-developers-part-3.html –

+0

@ChristopheGeers Exactement ... C'est assez compliqué de le faire soi-même, Les membres de MembershipProviders fonctionnent bien, ils doivent être configurés pour le faire. – sinni800

Répondre

1

Supposons que nous avons une table pour les comptes comme celui-ci

enter image description here

Ensuite, vous pouvez créer une classe d'aide qui retourne un objet compte

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; 
} 

J'utilise EntityFramework mais ce n'est pas important ici. L'idée principale est de montrer que vous n'avez pas besoin de toute la liste des comptes (surtout si vous avez une grande liste d'utilisateurs).
Ma classe Cryptographer ressemble

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); 
     } 
    } 
} 

Evidement, vous pouvez mettre en œuvre l'algorithme de votre propre.

+0

Merci, c'est exactement le type de commentaires que je cherchais ... En ce qui concerne l'utilisation de Rfc2898DeriveBytes vs RNGCryptoServiceProvider et FormsAuthentication.HashPasswordForStoringInConfigFile ... Qui a l'algorithme de hachage plus fort? En ce qui concerne l'obtention d'une liste complète d'utilisateurs, d'autres méthodes permettant de vérifier le mot de passe, l'incUserID limite le contrôle du mot de passe à celui-là, donc je veux dire qu'il sélectionne la base de données entière le EntityFramework ferait exactement la même chose ne le ferait-il pas? – user1474120

+0

@ user1474120 - Le principal problème que vous allez rencontrer est l'écriture de requêtes SQL sécurisées. Basé sur votre propre code, vous n'utilisez pas un schéma de mot de passe sécurisé, ce qui pose problème, mais l'obtention de l'utilisateur et du mot de passe de manière sécurisée est un problème plus important. –

+0

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