2012-06-22 13 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まさしく...あなた自身で行うのはかなり面倒ですが、組み込みのMembershipProvidersはうまくいきますが、そうするためには設定が必要です。 – sinni800

答えて

1

たちは、あなたがアカウントオブジェクトに

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

を返すいくつかのヘルパークラスを作成することができ、この

enter image description here

のようなアカウントのテーブルがあるとし私はEntityFrameworkを使用していますが、ここでは重要ではありません。主なアイデアは、アカウントのリスト全体を取得する必要がないことを示しています(特に、大きなユーザーリストがある場合)。
Cryptographerクラスは

あなた自身のアルゴリズムを実装することができ讲义1コースの
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対RNGCryptoServiceProviderとFormsAuthentication.HashPasswordForStoringInConfigFileを使用することについて...強力なハッシュアルゴリズムを持っていますか?限り、ユーザーの全体のリストを取得する限り、他のメソッドは実際に特定のユーザーにパスワードを確認する取得処理、incUserIDは、その1つだけにパスワードチェックを制限するので、それは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