Mã hóa chuỗi kết nối vào webconfig trong Nhibernate


Thông thường khi sử dụng Nhibernate để phát triển ứng dụng web hay ứng dụng winform chúng ta thường bỏ chuỗi kết nối ở file hibernate.cfg.xml , mình thấy bỏ thế nào không an toàn nên sau khi google với tìm hiểu mình đã tìm ra cách để bỏ vào webconfig và mã hóa chuỗi kết nối này cho nó an toàn nhằm tránh shell 爆笑

Thông thường thì chuỗi kết nối cơ sở dữ liệu thường bỏ ở file hibernate.cfg.xml như sau :

<property name="connection.connection_string">
      Chuỗi kết nối cơ sở dữ liệu ở đây

    </property>

Để mã hóa chuỗi kết nối ta viết một lớp là Crypto để mã hóa và giải mã trước đã

public static class Crypto
   {
       const string InitialVector = "4AQYuEmZ3Q7gNHdj";       
       public static string Encrypt(string data,string pass)
       {
           if (string.IsNullOrEmpty(data)) return "";

           var initialVectorBytes = Encoding.ASCII.GetBytes(InitialVector);
           var plainTextBytes = Encoding.UTF8.GetBytes(data);
           var keyBytes = Encoding.ASCII.GetBytes(pass);

           var symmetricKey = new RijndaelManaged();
           symmetricKey.Mode = CipherMode.CBC;
           byte[] cipherTextBytes = null;
           using (var encryptor = symmetricKey.CreateEncryptor(keyBytes, initialVectorBytes))
           {
               using (var memStream = new MemoryStream())
               {
                   using (var cryptoStream = new CryptoStream(memStream, encryptor, CryptoStreamMode.Write))
                   {
                       cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
                       cryptoStream.FlushFinalBlock();
                       cipherTextBytes = memStream.ToArray();
                       memStream.Close();
                       cryptoStream.Close();
                   }
               }
           }
           symmetricKey.Clear();
           return Convert.ToBase64String(cipherTextBytes);         
       }     
       public static string Decrypt(string data,pass)
       {
           if (string.IsNullOrEmpty(data)) return "";

           var initialVectorBytes = Encoding.ASCII.GetBytes(InitialVector);
           var cipherTextBytes = Convert.FromBase64String(data);
           var keyBytes = Encoding.ASCII.GetBytes(pass);

           var symmetricKey = new RijndaelManaged();
           symmetricKey.Mode = CipherMode.CBC;
           var plainTextBytes = new byte[cipherTextBytes.Length];
           var byteCount = 0;
           using (var decryptor = symmetricKey.CreateDecryptor(keyBytes, initialVectorBytes))
           {
               using (var memStream = new MemoryStream(cipherTextBytes))
               {
                   using (var cryptoStream = new CryptoStream(memStream, decryptor, CryptoStreamMode.Read))
                   {
                       byteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);
                       memStream.Close();
                       cryptoStream.Close();
                   }
               }
           }
           symmetricKey.Clear();
           return Encoding.UTF8.GetString(plainTextBytes, 0, byteCount);           
       }    
   }

Mục đích của lớp này là mã hóa theo pass và giải mã theo pass một chuỗi, mục đích là mã hóa chuỗi kết nối.

Để sửa lại phương thức lấy chuỗi kết nối ta override lại lớp NHibernate.Connection.DriverConnectionProvider như sau :

public class MyConnectionProvider : NHibernate.Connection.DriverConnectionProvider
    {
        static string conn = "";
        protected override string ConnectionString
        {
            get
            {
                if (string.IsNullOrEmpty(conn))
                {

                    string connectionString = ConfigurationManager.ConnectionStrings["ApplicationServices"].ConnectionString;
                    conn= Crypto.Decrypt(connectionString,"sokhanh03");
                }
                return conn;
            }
        }       
       
    }

Sửa file hibernate.cfg.xml như sau :

<property name="connection.provider">
      (Name space của MyConnectionProvider).MyConnectionProvider,Name space của MyConnectionProvider
      <!–NHibernate.Connection.DriverConnectionProvider–>
    </property>

Chú ý comment lại dòng NHibernate.Connection.DriverConnectionProvider

Sau đó vào file webconfig hay app.config sửa lại thành :

<connectionStrings>
        <add name="ApplicationServices" connectionString="Chuỗi kết nối đã mã hóa với pass là sokhanh03" providerName="System.Data.SqlClient"/>
    </connectionStrings>

Như vậy ta đã chuyển chuỗi kết nối từ file hibernate.cfg.xml sang file webconfig(app.config) đã mã hóa, sau đó tiến hành code bình thường.

Mục đích của việt này là tránh việc bị shell đọc file webconfig và lấy chuỗi kết nối

Chúc các bạn thành công!

Nếu vẫn không làm được vui lòng comment lại ở đây mình sẽ support cho 爆笑

Phân trang trong Nhibernate


Đây là lớp giúp phân trang trong Nhibernate với Lớp T

public abstract class Paging<T>
   {
      public IList<T> GetPagedData(int page, int pageSize, out long count, Order oder, params ICriterion[] criterion)
      {
          IMultiCriteria multiCriteria  = NHibernateHelper.CurrentSession.CreateMultiCriteria();
          ICriteria criteria1 = NHibernateHelper.CurrentSession.CreateCriteria(typeof(T));
          ICriteria criteria2 =
              NHibernateHelper.CurrentSession.CreateCriteria(typeof (T));//.SetProjection(Projections.RowCountInt64());
          foreach (var item in criterion)
          {
              criteria1.Add(item);
              criteria2.Add(item);
          }
          criteria2.SetProjection(Projections.RowCountInt64());
          criteria1.AddOrder(oder);         
          multiCriteria.Add(criteria1);
          multiCriteria.Add(criteria2);
         // page = page > 0 ? page : 1;
          criteria1.SetFirstResult(page * pageSize).SetMaxResults(pageSize);          
          IList result = multiCriteria.List();
          IList<T> all = (from object o in (IList) result[0] select (T) o).ToList();
          count = (long)((IList)result[1])[0];
          return all;
      }
   }

Lớp NHibernateHelper

public sealed  class NHibernateHelper
    {
      private static ISessionFactory factory = null;
      static NHibernateHelper()
        {
            Configuration cfg = new Configuration();
            cfg.Configure();
            factory = cfg.BuildSessionFactory();
        }

        public static ISession CurrentSession
        {
            get
            {
                if(factory==null)
                {
                    var configuration = new Configuration();
                    configuration.Configure();
                    factory = configuration.BuildSessionFactory();
                }
                return factory.OpenSession();
            }
        }
        public static void CloseSession()
        {
            factory.Close();
        }
    }

Chú ý : đối với hệ quản trị Mysql không hỗ trợ MultiCriteria ta có thể viết lại lớp Paging như sau :

public abstract class Paging<T>
   {

    public IList<T> GetPagedData(int page, int pageSize, out long count, Order oder, params ICriterion[] criterion)
        {
           // IMultiCriteria multiCriteria = NHibernateHelper.CurrentSession.CreateMultiCriteria();
            ICriteria criteria1 = NHibernateHelper.CurrentSession.CreateCriteria(typeof(T));
            ICriteria criteria2 =
                NHibernateHelper.CurrentSession.CreateCriteria(typeof(T));//.SetProjection(Projections.RowCountInt64());
            foreach (var item in criterion)
            {
                criteria1.Add(item);
                criteria2.Add(item);
            }
            criteria2.SetProjection(Projections.RowCountInt64());
            criteria1.AddOrder(oder);
           // multiCriteria.Add(criteria1);
           // multiCriteria.Add(criteria2);
            criteria1.SetFirstResult(page * pageSize).SetMaxResults(pageSize);
            count = long.Parse(criteria2.List()[0].ToString());
            return   criteria1.List<T>();
           // IList result = multiCriteria.List();
           // IList<T> all = (from object o in (IList)result[0] select (T)o).ToList();
           // count = (long)((IList)result[1])[0];
           // return all;
        }
    }

CodeRun – Online IDE cho các dự án web C#, PHP, Javascript


Được xây dựng trên  SharpKit C# to JavaScript Compiler, CodeRun (http://www.coderun.com) được sử dụng để tạo các dự án web để lập trình theo mô hình cloud computing (điện toán đám mây). CodeRun hỗ trợ nhiều loại dự án C# như  Sharpkit, Silverlight, Facebook, ASP.NET, …, bên cạnh đó còn có Javascript và PHP.

Giới thiệu

Giao diện của CodeRun rất đơn giản và thân thiện, có thể coi là một IDE rút gọn của Visual Studio.  Hiện tại CodeRun hỗ trợ các dự án C# (3.5), PHP (5.1), Javascript, HTML và CSS. Database hỗ trợ gồm có SQL Server 2005 và Amazon SimpleDB.

coderun-ide-new-project

Các tính năng và hỗ trợ của CodeRun được liệt kê trong bảng sau:

Language/ Platform

Syntax
Coloring

Code
Completion

Compilation

Server Side
Debugging

Hyperlink
code
sharing

Single Click
Deployment

C# / ASP.NET

Yes

Yes

Yes

Yes

Yes

Yes

C# / WPF

Yes

Yes

Yes

Yes

Yes

Yes

C# / Silverlight

Yes

Yes

Yes

Yes

Yes

Yes

PHP

Yes

No

N/A

No

Yes

Yes

JavaScript

Yes

No

N/A

No

Yes

Yes

HTML

Yes

No

N/A

No

Yes

Yes

CSS

Yes

No

N/A

No

Yes

Yes

 

Để bắt đầu, bạn hãy nút sau:

Một ví dụ với dự án PHP Web Site để hiển thị thông tin phiên bản PHP được sử dụng:

coderun-ide-php-info

Video hướng dẫn

CodeRun cung cấp một số video hướng dẫn, bạn có thể xem tại link sau hoặc xem trực tiếp từ các video bên dưới:

http://www.coderun.com/tv/

HOWTO: Create and run a simple ASP.NET application with CodeRun Online IDE

 

HOWTO: Debug an ASP.NET application with CodeRun Online IDE

 

HOWTO: Share runnable code with CodeRun Online IDE

 

Online Code Search

Các dự án của bạn lưu trên CodeRun sẽ public và được bình chọn, bạn có thể tìm kiếm cho mình những dự án nguồn mở hữu ích trên trang này (http://www.coderun.com/code/)

Sử dụng thư viện HtmlAgilityPack để xử lý văn bản html


Việc xử  lý văn bản html và trích xuất các phần tử  dom trong văn bản html thường gây cho LTV chúng ta gặp nhiều khó khăn, một giải pháp mà người ta hay dùng là dùng regex để tách các đoạn các thẻ trong văn bản html, nay chúng ta có thể sử  dụng thư  viện HtmlAgilityPack và dùng LINQ để truy vấn sẽ đơn giản hơn nhiều

Đầu tiên download thư  viện : HtmlAgilityPack tại đây

vào visual studio add file HtmlAgilityPack.dll vào Refercences

Ví dụ :

Đầu tiên tạo 1 request đến trang http://dantri.com.vn

string root = “http://dantri.com.vn&#8221;;
WebRequest request = WebRequest.Create(root);
WebResponse response = request.GetResponse();
// Display the status.
Console.WriteLine(((HttpWebResponse)response).StatusDescription);
// Get the stream containing content returned by the server.
var dataStream = response.GetResponseStream();
// Open the stream using a StreamReader for easy access.
StreamReader reader = new StreamReader(dataStream);
// Read the content.
string responseFromServer = reader.ReadToEnd();
// Display the content.
Console.WriteLine(responseFromServer);
// Clean up the streams.
reader.Close();
dataStream.Close();
response.Close();

Sau khi thực hiện lệnh này mã html sẽ nằm ở biến responseFromServer chúng ta bắt đầu xử  lý sử  dụng thư  viện trên

Lấy tất cả link có trong trang :

HtmlDocument doc = new HtmlDocument();
doc.LoadHtml(responseFromServer);

List<HtmlNode> links = (from node in doc.DocumentNode.SelectNodes(“//a[@href]”).Cast<HtmlNode>()
where ((node.Attributes[“href”].Value.StartsWith(“/”)) & (node.Attributes[“href”].Value.EndsWith(“.htm”)))
select node).ToList<HtmlNode>();

Lấy tất cả thẻ div có class là : fon31 mt1

 var title = (from m in doc.DocumentNode.SelectNodes(“//div[@class]”).Cast<HtmlNode>()
where m.Attributes[“class”].Value == “fon31 mt1”
select m).ToList<HtmlNode>();

….

Để lấy được nội dung của đoạn text ta sử  dụng thuộc tính InnerHtml trong class HtmlNode 😀

Để xử  lý các truy vấn khác các bạn cần biết đến Xpath

Vậy ứng dụng của việc này để làm gì?

– Các bạn có thể một tool lấy tin tự  động từ  dân trí hay các trang khác ^_^!

– Sử  dụng để viết Web crawler 🙂

Nhận xét :

Có nhiều cách để làm được việc cần nói ở trên nhưng các này đơn giản và viết ngắn gọn hơn ^_^!

Giới thiệu Tuple trong .NET 4.0


Trong phiên bản sắp phát hành Microsoft .NET Framework 4.0 sẽ xuất hiện một kiểu dữ liệu mới là System.Tuple. System.Tuple là một kiểu tập hợp có kích thước cố định được dùng để lưu trữ tập các đối tượng có kiểu dữ liệu khác nhau. Cũng giống như kiểu mảng trước đây, một tuple sẽ có kích thước cố định và không thể thay đổi sau khi được khởi tạo thành công. Điểm khác biệt so với kiểu mảng là mặc dù các phần tử trong tuple có thể có kiểu dữ liệu khác nhau nhưng mỗi phần tử trong tuple được đảm bảo về kiểu dữ liệu của mình. Để hiểu rõ hơn, hãy xét một ví dụ sau đây:

 

Code Snippet
  1. static void Main(string[] args)
  2.         {
  3.             object[] objects = new object[3];
  4.             objects[0] = "This is a string";
  5.             objects[1] = 1;
  6.             objects[2] = new DateTime(2009, 10, 24);
  7.             PrintObjects((string)objects[0], (int)objects[1], (DateTime)objects[2]);
  8.         }
  9.         static void PrintObjects(string str, int i, DateTime dt)
  10.         {
  11.             Console.WriteLine("{0} {1} {2}", str, i, dt.ToString());
  12.         }

Ví dụ trên tạo ra một mảng gồm 3 phần tử có kiểu là object. Thoạt nhìn, đoạn code trên không có vấn đề gì nảy sinh. Nhưng nếu xét về mặt an toàn kiểu dữ liệu (type safety) thì đoạn code trên mắc rất nhiều lỗi. Khi khai báo một mảng các object như vậy, thì ta có thể đưa vào đó bất kỳ thứ gì ta muốn và không thể kiểm soát được. Trong trường hợp, nếu như tại phần tử thứ 2, ta đưa vào là một chuỗi ký tự như sau:

Code Snippet
  1. static void Main(string[] args)
  2.         {
  3.             object[] objects = new object[3];
  4.             objects[0] = "This is a string";
  5.             objects[1] = "This is an another string";
  6.             objects[2] = new DateTime(2009, 10, 24);
  7.             PrintObjects((string)objects[0], (int)objects[1], (DateTime)objects[2]);
  8.         }

Đoạn code sau khi sửa xong vẫn sẽ biên dịch thành công. Nhưng khi gọi thực thi phương thức PrintObjects thì sẽ bị lỗi InvalidCastException khi thực hiện việc chuyển đổi chuỗi “This is an another string” sang kiểu số int.

Bây giờ, cùng ví dụ trên, nhưng ta sử dụng System.Tuple

Code Snippet
  1. static void Main(string[] args)
  2.         {
  3.             System.Tuple<string, int, DateTime> tuple = new Tuple<string, int, DateTime>
  4.             ("This is a string", 1, new DateTime(2009, 10, 24));
  5.             PrintObjects(tuple.Item1, tuple.Item2, tuple.Item3);
  6.         }

Với cách giải quyết vấn đề bằng việc sử dụng System.Tuple, ta có thể loại bỏ các phép toán “ép kiểu” (cast operators) ra khỏi chương trình, điều này giúp cho việc kiểm tra lỗi tại thời điểm biên dịch tốt hơn. Với ví dụ vừa nêu ở trên, ta thấy rằng System.Tuple là một kiểu dữ liệu hữu ích và cần phải có trong .NET Framework.

System.Tuple và KeyValuePair

Hãy xem một phương thức khởi tạo của Tuple như sau:

public static System.Tuple<T1,T2> Create<T1, T2>(T1 item1, T2 item2)

Từ các phiên bản trước của .NET Framework, đã có một kiểu dữ liệu có tên là KeyValuePair<Tkey, Tvalue> nằm trong namespace System.Collections.Generic. Cả hai kiểu Tuple<T1, T2> và KeyValuePair<Tkey, Tvalue> đều rất giống nhau. Thật ra, giữa Tuple<T1, T2> và KeyValuePair<Tkey, Tvalue> có khá nhiều điểm khác biệt. Đối với KeyValuePair<Tkey, Tvalue>, ngoài việc lưu trữ 2 thành phần Tkey và Tvalue, nó còn mang kèm cả “mối quan hệ” giữa 2 thành phần này – và cũng với lý do này, KeyValuePair<Tkey, Tvalue> được dùng trong Dictionary class. Bên cạnh đó, tuples khi khởi tạo có thể thay đổi được kích thước lưu trữ, còn đối với KeyValuePair thì mặc nhiên chỉ lưu trữ duy nhất 2 thành phần là Tkey và Tvalue.

Đối với System.Tuple, ta có các phương thức khởi tạo sau:

Code Snippet
  1.         Tuple <T1>
  2.         Tuple <T1, T2>
  3.         Tuple <T1, T2, T3>
  4.         Tuple <T1, T2, T3, T4>
  5.         Tuple <T1, T2, T3, T4, T5>
  6.         Tuple <T1, T2, T3, T4, T5, T6>
  7.         Tuple <T1, T2, T3, T4, T5, T6, T7>
  8.         Tuple <T1, T2, T3, T4, T5, T6, T7, TRest>

 

Tham khảo bài viết CLR Inside Out: Building Tuple tại http://msdn.microsoft.com/en-us/magazine/dd942829.aspx