Trong phát triển phần mềm, các bạn thường hay nghe đến các khái niệm Dependency Injection, SQL Injection, etc nhưng không hiểu nó như thế nào.Thực ra các cơ chế này thì vốn rất đơn giản, chả có gì đặc biệt.Bài viết này mình sẽ giải thích về nguyên lý Injection và Ví dụ liên quan trong Software Engineering
Ai cần đọc bài này:
- Dành cho dân chuyên đã biết rồi có cách để tiết kiệm time để giải thích hoặc chém cho các bạn không biết gì.
- Dân không chuyên, không biết gì có thể hiểu và tự tin chém về các nguyên lý Injection trong Software Engineering.
- Dành cho việc tham khảo giúp các bạn lười giải thích chia sẻ cho nhau.
I. Injection là gì?
Trước hết các bạn cần hiểu Injection là gì?
Injection dịch trần từ tiếng Anh thì là sự tiêm chích, tiêm nhiễm. Ex: tiêm thuốc phòng, tiêm chích ma túy, etc.
Kết quả của việc tiêm này thì có thể mang lại hiệu ứng tốt hoặc xấu tùy vào mình tiêm thuốc hay là ma túy hoặc tiêm thuốc độc dành cho việc tử hình các tử tù ở Việt Nam hay 1 số nước trên thế giới.
Nhìn 1 cách khái quát hơn, quá trình tiêm là cho thuốc hoặc chất kích thích vào hệ tuần hoàn máu của cơ thể và lợi dụng hệ tuần hoàn máu này để làm thay đổi (tốt hoặc xấu) đến cơ thể.
Tuy nhiên ví dụ ở trên là tôi đang nói về việc tiêm thuốc dịch trần tiếng anh là Vaccine Injection. Nó chỉ là 1 trường hợp của Injection trong tiếng Anh thôi.
Thật ra Injection trong tiếng Anh thì có thể tiêm (injection) rất nhiều các loại khác ngoài thuốc. Ví dụ như trong Software Engineering thì có các khái niệm như SQL Injection, OS command Injection, Dependency Injection.
Do từ vựng tiếng việt hạn chế nên người ra dịch là tiêm, và chỉ có từ tiêm thuốc là map với injection nên mọi người chỉ nghĩ đến là việc tiêm thuốc. Và hiện chưa có từ nào để map với từ injection này nên làm cho mọi người bị hiểu lầm là việc tiêm thuốc (vốn chỉ là 1 trong các trường hợp cụ thể của injection trong tiếng Anh). Nói chung việc phối giống cho gà hay thụ tinh ở người thì tiếng anh cũng có thể gọi là 1 quá trình injection do tác động vào cơ chế sinh sản có sẵn.
Tôi thì không phải là nhà ngôn ngữ học nên cũng không dám định nghĩa thêm từ tiếng việt nào đáp ứng chính xác với từ Injection. Cho nên từ các đoạn tiếp theo tôi sẽ dùng từ Injection cho nó phân biệt với từ “tiêm” trong tiếng Việt nhé.
Nói 1 cách trừu tượng hóa Injection là sự tác động đến đến cơ chế có sẵn và lợi dụng cơ chế này cho 1 mục đích nào đó.
Như trường hợp tiêm thuốc thì là dùng thuốc tác động đến cơ chế tuần hoàn máu. Và nhờ cơ chế này thuốc được phát tán khắp cơ thể.
Ở trong phát triển phầm mềm thì cơ chế này cũng y hệt như vậy. Nếu hiểu như trên thì cơ chế này thì vốn rất simple, chả có gì đặc biệt đúng không nào?
Đi sâu phân tích sâu thêm 1 chút thì để thực hiện được việc injection đầy đủ thì sẽ cần các đối tượng sau :
- Đối tượng cần inject.
- Lỗ hổng của cơ chế.
- Cơ chế sẵn có.
Tôi xin phép ví dụ trường hợp tiêm thuốc (1 trong các trường hợp của injection) thì sẽ như sau :
- Đối tượng cần inject: thuốc.
- Lỗ hổng: lỗ, ven mạch máu để có thể tiêm tác động vào hệ tuần hoàn.
- Cơ chế sẵn có: hệ tuần hoàn máu.
Ở đây tôi không nói đến kết quả của việc injection vì nói chung mục đích cuối cùng là sẽ tác động thay đổi đến vật chủ, kết quả tốt hay xấu không bàn ở đây.
Như ví dụ tôi nói ở trên thì quá trình tiêm thuốc mọi người đều không để ý đến 1 đối tượng rất quan trọng, đó là “lỗ hổng” – nói một cách dễ hiểu..
Khi thực hiện tiêm thì sẽ cần tìm lỗ ven mạch máu đầu tiên. Nếu như trên cơ thể không có 1 cái “lỗ” nào để có thể chọc kim tiêm vào, thì sẽ không cách nào tác động vào hệ tuần hoàn máu để hoàn thành việc tiêm thuốc(injection).
Và trong các khái niệm về Injection trong Software Engineering thì cái “lỗ” cũng rất quan trọng, và bao giờ bắt đầu việc injection thì người ta sẽ cần tìm đến cái “lỗ” đầu tiên như việc bắt đầu quá trình giao phối của các loài động vật có vú.
Các phần tiếp theo tôi cũng đề cập đến các “lỗ” hổng này và các bạn nhớ chú ý nhé.
II – SQL Injection
SQL Injection thì trong Software Engineering thường nói đến lỗ hổng bảo mật của phầm mềm cho phép người dùng có thể truy nhập trực tiếp vào cơ sở dữ liệu (database) của cả hệ thống nhằm ăn cắp thông tin, phá hoại hệ thống.
Trước hết dành cho ai chưa biết, SQL ở đây là các câu lệnh dùng để truy nhập vào database của 1 hệ thống.
Cũng giống như việc tiêm thuốc, thay vì inject thuốc thì có thể inject các câu lệnh SQL từ bên ngoài thông qua cơ chế truy nhập cơ sở dữ liệu của phần mềm. Các đối tượng trong việc injection này bao gồm :
- Đối tượng cần inject: các câu lệnh SQL.
- Lỗ hổng: các nguồn input từ người dùng bên ngoài. Ex: nhập user name, password, nhập thông tin trên trang web, phần mềm.
- Cơ chế sẵn có: cơ chế truy nhập đến cơ sở dữ liệu của hệ thống.
Ví dụ như khi tôi viết blog trên trang web này. Tôi thay vì viết nội dung blog mà thay vào đó, thêm các câu lệnh SQL thay đổi database của hệ thông web để sửa 1 topic của tôi thì rank cao nhất, rate cao nhất để ăn tiền công viết chẳng hạn.
Cũng giống như việc tiêm thuốc thôi, thay vì tôi tiêm (inject) thuốc để chữa bệnh hay làm chết người thì tôi Inject SQL vào hệ thông để chỉnh sửa data của hệ thống hoặc làm chết hệ thống.
Về mặt bảo mật thông tin khi mà người dùng thoải mái lấy hoặc thay data của hệ thống thông qua việc inject các câu lệnh SQL như trên là rất nguy hiểm.
Ví dụ: ăn cắp thông tin, sửa dổi tài khoản trên hệ thống tài chính, ngân hàng. Ăn cắp bảng lương của công ty thông qua trang web quản lý của công ty.
Như tôi đã nói ở trên lỗ hổng rất quan trọng để thực hiện việc injection, ở đây lỗ hổng là từ input của người dùng, khi mà người dùng thoải mái inject các câu lệnh SQL để thay đổi cả hệ thống.
Cho nên về mặt bảo mật thông tin thì việc kiểm tra, validate các nguồn input này của người dùng để ngăn chặn truy nhập trực tiếp vào là rất quan trọng. Tương tự còn có khái niệm khác về bảo mật như OS Command Injection, trường hợp này thì là inject các câu lệnh gọi đến hệ điều hành của hệ thống nhằm cướp quyền kiểm soát hoặc phá hoại. Về nguyên lý nó vốn đơn giản như việc tiêm đã giải thích ở phần I.
III – Dependency Injection
Để hiểu được về cơ chế Dependency Injection trước hết bạn cần phải hiểu trước về nguyên lý Dependency inversion. Tuy nhiên về Dependency inversion thì lại là khái niệm hơi loằng ngoằng 1 chút, cơ mà nó vấn đơn giản.
Để giải thích tôi bắt đầu với ví dụ sau:
Bạn là ông chủ của công ty, hàng ngày cứ đến chiều về phải xem lại thông tin tổng kết doanh thu của công ty. Và để làm được thư ký của bạn sẽ phải bắn mail tổng kết hàng ngày. Tuy nhiên ngày nào bạn cũng phải mất công giục bạn thư ký phải viết báo cáo đúng giờ, rồi lúc thì cần thông tin này lúc thì cần thông tin kia. Nói chung là công việc của bạn rất phụ thuộc vào bạn thư ký.
Thời gian sau đó bạn rút kinh nghiệm sâu sắc, soạn template, ra quy định về thời gian báo cáo bắt thư ký phải làm theo. Và sau đó cứ đến chiều là bạn xem thông tin tổng kết doanh thu của công ty mà không cần phải giục hay phụ thuộc nhiều vào thư ký nữa.
Như vậy có phải là sự phụ thuộc vào bạn thư ký đã bị đảo ngược đúng không? bạn thư ký sẽ phải tuân theo các điều kiện mà bạn qui định thay vì bạn phải chạy theo và giục thư ký viết báo cáo.
Quá trình đảo ngược sự phụ thuộc này trong phần mềm gọi là nguyên lý dependency inversion. Module gọi sẽ đưa ra các phương thức, qui định để dependency module phải tuân theo khi thực hiện 1 chức năng nào đó của phần mềm.
Như trong ví dụ trên thì sau khi ra các qui định trên thì bạn có thể thay thế bất ký cô thư ký nào miễn là thỏa mãn điều kiện báo cáo đúng theo template và đúng giờ. Nói theo cách khác bạn có thể inject bất kỳ cô thư ký nào vào cơ chế xem lại thông tin tổng kết doanh thu của công ty.
Khái quát thêm chút thì một cô thư ký bất kỳ gọi là 1 sự phụ thuộc (dependency) trong cơ chế xem lại thông tin tổng kết doanh thu của công ty.
Cơ chế mà inject Dependency trên gọi là Dependency Injection.
Các đối tượng trong việc injection này bao gồm :
- Đối tượng cần inject: thư ký.
- Lỗ hổng: các quy định về template, ngày giờ báo cáo dành cho 1 thư ký bất kỳ.
- Cơ chế sẵn có: việc xem lại thông tin tổng kết doanh thu của công ty.
Thế còn về Software enginering thì sao? Thật ra cơ chế nó vãn như trên. Trong 1 phần mềm thì thường được thiết kế chia thành nhiều các thành phần nhỏ gọi là các module/class. Các module/class thường sẽ gọi nhau để thực hiện 1 chức năng của phần mềm.
Ví dụ: như khi người dùng login vào trang web này chẳng hạn thì thường sẽ có ít nhất 2 module sau gọi nhau bao gồm:
- Module chính (làm nhiệm vụ login, xác thực username/password).
- Module truy nhập vào cơ sở dữ liệu.
Module chính sẽ gọi đến module truy nhập vào cơ sở dữ liệu để lấy username/password rồi kiểm tra có hơp lệ để login hay không. Module được gọi đến cụ thể là module truy nhập vào cơ sở dữ liệu thì gọi là 1 dependency module hay còn dịch là module phụ thuộc của module chính. Dependency Injection là cơ chế inject bất kỳ dependency module khác vào cơ chế gọi đến nó.
Để làm được điều đó như các đã giải thích về cơ chế injection trong phần I thì để thực hiên được sẽ cần có 1 cái “lỗ” hổng, để tạo ra lỗ hổng này sẽ cần dựa trên nguyên lý dependency inversion (sự đảo ngược phụ thuộc) trong software design.
Cụ thể lỗ hổng được tạo ra ở đây là các phương thức, qui định mà dependency module bắt buộc phải cung cấp cho cơ chế gọi đến nó. Trong software design thì gọi là interface qui định các phương thức giữa 2 module.
Ví dụ như trong cơ chế login, dependency module sẽ cần cung cấp các inteface bao gồm phương thức để kiểm tra username, password trong database.
Các đối tượng trong việc injection của cơ chế login bao gồm :
- Đối tượng cần inject : dependency module mà truy nhập vào cơ sở dữ liệu.
- Lỗ hổng : inteface qui định các phương thức mà dependency module phải follow và cung cấp (dựa trên cơ chế Dependency Inversion đã nói ở trên)
- Cơ chế sẵn có : cơ chế login vào hệ thống.
Kết luận
Cơ chế Dependency Injection này rất có ý nghĩa trong việc phát triển phần mềm khai mà các đội trong dự án phát triển song song các module, unit test hoặc việc bảo trì thay đổi, mở rộng source code của module này nhưng không bị ảnh hưởng đến module khác.
Như tôi đã ví dụ cho trường hợp sếp và thư ký ở trên thì các bạn có thể thấy cơ Dependency Injection này rất có ý nghĩa ngay cả trong đời sống phải không?
Khái niệm Dependency Injection này vẫn đơn giản như việc tiêm thuốc đúng không?
Nếu hiểu rồi thì nhớ like và share nhé để tôi còn có động lực viết các blog khác 🙂
Nếu ai không hiểu góp ý để tôi update thêm nhé.