2012-06-22 31 views
5

Im a CS major và tôi vừa hoàn thành thiết kế trang ASP.net và cho trang web tôi cần hệ thống xác thực đăng nhập ... Tôi không muốn sử dụng SQLMembershipProvider vì tôi thực sự muốn tìm hiểu làm thế nào để tự mình làm ... Dù sao thì đây là điều tôi nghĩ ra, và tôi tự hỏi liệu có ai có thể cho tôi một số phản hồi, lời khuyên hay lời khuyên.Xác thực ASP.net

Cảm ơn trước

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

Nếu bạn muốn tạo nhà cung cấp tư cách thành viên tùy chỉnh, trước tiên bạn phải kế thừa từ MemberShipProvider. Và đây là tài liệu khá tốt nếu bạn google một chút. –

+2

Đừng cố gắng cuộn các chương trình quản lý phiên và xác thực tùy chỉnh của riêng bạn hoặc tạo các điều khiển của riêng bạn trừ khi bạn thực sự không có lựa chọn nào khác. Tôi chỉ muốn làm điều đó, không đủ điều kiện. Một điều thú vị: http://www.troyhunt.com/2010/07/owasp-top-10-for-net-developers-part-3.html –

+0

@ChristopheGeers Chính xác ... Nó khá cồng kềnh để tự mình làm, xây dựng trong MembershipProviders làm việc tốt, họ phải được cấu hình để làm như vậy. – sinni800

Trả lời

1

Giả sử chúng ta có một bảng cho các tài khoản như thế này

enter image description here

Sau đó, bạn có thể tạo một số lớp helper mà trả về một đối tượng tài khoản

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

Tôi đang sử dụng EntityFramework nhưng điều này không quan trọng ở đây. Ý tưởng chính cho thấy bạn không cần phải lấy toàn bộ danh sách tài khoản (đặc biệt nếu bạn có danh sách người dùng lớn).
lớp Cryptographer tôi trông như thế

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

Trong cource bạn có thể thực hiện các thuật toán của riêng bạn.

+0

Cảm ơn, đây chính xác là loại phản hồi mà tôi đang tìm kiếm ... Về việc sử dụng Rfc2898DeriveBytes vs RNGCryptoServiceProvider và FormsAuthentication.HashPasswordForStoringInConfigFile ... Thuật toán băm nào mạnh hơn? Theo như nhận được toàn bộ danh sách người dùng, các phương pháp khác thực sự xử lý việc người dùng cụ thể kiểm tra mật khẩu, incUserID giới hạn kiểm tra mật khẩu chỉ với mật khẩu đó, vì vậy tôi có nghĩa là nó chọn toàn bộ cơ sở dữ liệu chỉ với 1 lần trả về EntityFramework sẽ làm chính xác điều tương tự sẽ không? – user1474120

+0

@ user1474120 - Vấn đề chính bạn sẽ gặp phải là viết các truy vấn SQL an toàn. Dựa trên mã của riêng bạn, bạn không sử dụng lược đồ mật khẩu an toàn, đó là vấn đề, nhưng việc nhận người dùng và mật khẩu một cách an toàn là một vấn đề lớn hơn. –

+0

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

Các vấn đề liên quan