Xác thực dữ liệu đầu vào - Ở đâu? Bao nhiêu? [đóng cửa]


27

Xác thực dữ liệu đầu vào luôn là một cuộc đấu tranh nội bộ đối với tôi.

Trước khi thêm một khung bảo mật và mã bảo mật thực sự vào dự án viết lại ứng dụng cũ của chúng tôi (điều này cho đến nay vẫn giữ được mã bảo mật di sản mạnh mẽ của thẻ lâu đài và xác thực dữ liệu), tôi lại tự hỏi về việc tôi nên xác thực bao nhiêu, ở đâu, v.v.

Trong hơn 5 năm làm nhà phát triển Java chuyên nghiệp, tôi đã tạo và tinh chỉnh các quy tắc cá nhân của mình để xác thực dữ liệu và các biện pháp bảo mật. Khi tôi muốn cải thiện phương pháp của mình, tôi muốn nghe một số ý tưởng từ các bạn. Các quy tắc và quy trình chung đều ổn và các quy tắc cụ thể của Java cũng vậy.

Tóm tắt, đây là những hướng dẫn của tôi (được trình bày theo kiểu ứng dụng web 3 tầng), với lời giải thích ngắn gọn:

  • Phía máy khách cấp 1 (trình duyệt): xác thực tối thiểu, chỉ các quy tắc bất biến (trường email bắt buộc, phải chọn một mục và tương tự); việc sử dụng xác nhận bổ sung như "từ 6 đến 20 ký tự" ít thường xuyên hơn, vì điều này làm tăng công việc bảo trì đối với các thay đổi (có thể được thêm vào sau khi mã doanh nghiệp ổn định);

  • Phía máy chủ cấp 1 (xử lý giao tiếp web, "bộ điều khiển"): Tôi không có quy tắc cho điều này, nhưng tôi tin rằng chỉ nên xử lý lỗi thao tác và lắp ráp / phân tích dữ liệu ở đây (trường sinh nhật không phải là ngày hợp lệ); thêm xác nhận ở đây dễ dàng làm cho nó trở thành một quá trình thực sự nhàm chán;

  • Tầng thứ 2 (lớp nghiệp vụ): xác thực rắn, không kém; định dạng dữ liệu đầu vào, phạm vi, giá trị, kiểm tra trạng thái nội bộ nếu phương thức không thể được gọi bất cứ lúc nào, vai trò / quyền của người dùng, v.v. sử dụng càng ít dữ liệu đầu vào của người dùng càng tốt, lấy lại từ cơ sở dữ liệu nếu cần; nếu chúng tôi cũng xem xét việc lấy dữ liệu cơ sở dữ liệu làm đầu vào, tôi sẽ chỉ xác thực nó nếu một số dữ liệu cụ thể được biết là không đáng tin cậy hoặc bị hỏng đủ trên DB - gõ mạnh thực hiện hầu hết công việc ở đây, IMHO;

  • Tầng thứ 3 (lớp dữ liệu / DAL / DAO): không bao giờ tin rằng cần phải xác thực nhiều ở đây, vì chỉ có lớp doanh nghiệp được truy cập dữ liệu (có thể xác thực trong một số trường hợp như "param2 không được null nếu param1 là đúng"); tuy nhiên, lưu ý rằng khi tôi có nghĩa là "ở đây" tôi có nghĩa là "mã truy cập cơ sở dữ liệu" hoặc "phương thức thực thi SQL", thì chính cơ sở dữ liệu hoàn toàn ngược lại;

  • cơ sở dữ liệu (mô hình dữ liệu): cần phải được suy nghĩ cẩn thận, mạnh mẽ và tự thực thi để tránh dữ liệu không chính xác và bị hỏng trên DB càng nhiều càng tốt, với các khóa chính tốt, khóa ngoại, ràng buộc, loại / độ dài / kích thước dữ liệu / độ chính xác và vân vân - Tôi sẽ để lại các yếu tố kích hoạt, vì họ có cuộc thảo luận riêng.

Tôi biết xác thực dữ liệu sớm là tốt và hiệu suất, nhưng xác thực dữ liệu lặp đi lặp lại là một quá trình nhàm chán và tôi thừa nhận rằng chính xác thực dữ liệu là khá khó chịu. Đó là lý do tại sao rất nhiều lập trình viên bỏ qua nó hoặc làm điều đó nửa chừng. Ngoài ra, mọi xác thực trùng lặp là một lỗi có thể xảy ra nếu chúng không được đồng bộ hóa mọi lúc. Đó là những lý do chính mà ngày nay tôi thích để hầu hết các xác nhận hợp lệ cho tầng doanh nghiệp, với chi phí thời gian, băng thông và CPU, các trường hợp ngoại lệ được xử lý theo từng trường hợp cụ thể.

Vậy, bạn nghĩ gì về điều này? Phản đối ý kiến? Bạn có thủ tục khác? Một tài liệu tham khảo cho chủ đề như vậy? Bất kỳ đóng góp là hợp lệ.

Lưu ý: nếu bạn đang nghĩ cách làm Java, ứng dụng của chúng tôi là Spring dựa trên Spring MVC và MyBatis (hiệu suất và mô hình cơ sở dữ liệu xấu loại trừ các giải pháp ORM); Tôi dự định thêm Spring Security làm nhà cung cấp bảo mật của chúng tôi cộng với JSR 303 (Trình xác thực Hibernate?)

Cảm ơn!


Chỉnh sửa: một số làm rõ thêm trên lớp thứ 3.


Lời khuyên của tôi là nghiên cứu cách thức hoạt động của Trình xác thực Hibernate. Tôi đã không thấy JSR 303 là hữu ích, vì việc xác thực bắt đầu trong khi kiên trì, trong khi một số quy tắc của tôi phải được thi hành nhiều trước khi kiên trì, vì tôi có các quy tắc kinh doanh dựa trên xác nhận cơ bản. Theo tôi, Nó hoạt động cho một mô hình rất kín; có thể tôi đã sử dụng nó không chính xác, nhưng tôi chưa bao giờ tìm thấy ai có kinh nghiệm khác với tôi.
Vineet Reynold

@Vineet Reynold Tôi đã sử dụng nó để xác thực mẫu với Spring MVC, đây thực sự là một sự kết hợp tuyệt vời. Tôi nhận được xác thực phía máy chủ với các tin nhắn chi tiết với ít hoặc không cần nỗ lực, lỗi thích hợp được hiển thị cho người dùng. Tôi vẫn đang thử nghiệm nó hoàn toàn trên các đối tượng phía máy chủ, không chắc chắn về những lợi thế. Hãy xem bài đăng mẫu này, đó là cách tôi đã sử dụng nó: codemunchies.com/2010/07/ trên
mdrg

2
đặt quá nhiều xác nhận. Mọi nơi đều làm hỏng những đầu vào của người dùng @ #! ! @@!
Chani

Câu trả lời:


17

Xác nhận của bạn phải nhất quán. Vì vậy, nếu người dùng nhập một số dữ liệu trên biểu mẫu web được xác định là hợp lệ thì không nên từ chối lớp cơ sở dữ liệu vì một số tiêu chí bạn không thực hiện ở phía máy khách.

Là một người dùng, sẽ không có gì khó chịu hơn khi nhập vào một trang dữ liệu rõ ràng chỉ được thông báo sau một chuyến đi khứ hồi quan trọng đến cơ sở dữ liệu rằng có gì đó không đúng. Điều này sẽ đặc biệt đúng nếu tôi vấp phải một số xác nhận của khách hàng trong quá trình này.

Bạn cần phải có xác nhận ở nhiều cấp độ khác nhau khi bạn phơi bày những điều này và có khả năng không kiểm soát được ai gọi chúng. Vì vậy, bạn cần sắp xếp (càng xa càng tốt) để xác thực của bạn được xác định ở một nơi và được gọi từ bất cứ nơi nào cần thiết. Làm thế nào điều này được sắp xếp sẽ phụ thuộc vào ngôn ngữ và khuôn khổ của bạn. Trong Silverlight (ví dụ), bạn có thể xác định nó ở phía máy chủ và với các thuộc tính phù hợp, nó sẽ được sao chép sang phía máy khách để sử dụng ở đó.


2
+1 Hoàn toàn. Tôi sẽ nói điều tương tự về ASP.NET MVC, nhưng bạn đã đánh bại tôi. :) Thực sự, chúng tôi chỉ CẦN xác nhận tại chỗ để đảm bảo hệ thống luôn ở trạng thái hợp lệ. Phần còn lại của xác nhận như phía khách hàng là để tăng cường khả năng sử dụng và lãng phí thời gian cho người dùng, vì vậy đó phải là trọng tâm chính. Tính nhất quán là chìa khóa.
Ryan Hayes

2
Về "chuyến đi khứ hồi", tôi thấy không có vấn đề gì miễn là trang được tải lại với các thông báo lỗi thích hợp và tất cả các trường được điền với bất cứ điều gì bạn đã nhập trước đó (hầu hết các giao diện đều thiếu chi tiết cuối cùng này). Nếu mất quá nhiều thời gian để khắc phục lỗi, thì đó là một ứng cử viên để xác nhận phía khách hàng bổ sung.
mdrg

Và chắc chắn, nếu xác thực có thể được nhân rộng dễ dàng trên ứng dụng, không có lý do gì để lãng phí điều đó. Về phía máy chủ thì dễ, nhưng về phía máy khách, không có các công cụ xác thực như công cụ bạn đã đề cập, sẽ rất bực bội (ví dụ: viết rất nhiều mã xác thực JS, giống như mã bạn đã viết ở máy chủ) .
mdrg

9

Trong một hệ thống quan hệ, tôi thấy nó là một cách tiếp cận ba lớp. Mỗi lớp bị ràng buộc bởi những cái bên dưới:

  • Trình bày / UI
    • xác nhận đầu vào đơn giản
    • không tiếp tục nếu đầu vào sai định dạng
    • Yêu cầu máy khách "cổng" đến máy chủ để giảm các chuyến đi khứ hồi, cho khả năng sử dụng tốt hơn và giảm băng thông / thời gian
  • Logic
    • logic kinh doanh và ủy quyền
    • đừng để người dùng làm những việc họ không được phép làm
    • xử lý các thuộc tính và trạng thái "dẫn xuất" ở đây (những thứ sẽ được chuẩn hóa trong cơ sở dữ liệu)
  • Dữ liệu
    • lớp toàn vẹn dữ liệu cần thiết
    • tuyệt đối từ chối lưu trữ bất kỳ rác
    • chính DB thực thi các định dạng dữ liệu (int, date, v.v.)
    • sử dụng các ràng buộc cơ sở dữ liệu để đảm bảo các mối quan hệ đúng đắn

Các lý tưởng câu trả lời cho điều này sẽ là một hệ thống cho phép bạn xác định những hạn chế ở tất cả ba lớp ở một nơi. Điều này sẽ liên quan đến việc tạo mã cho SQL và ít nhất là xác thực dựa trên dữ liệu cho máy khách và máy chủ.

Tôi không biết có viên đạn bạc nào ở đây không ... nhưng vì bạn đang sử dụng JVM, tôi khuyên bạn nên xem Rhino để chia sẻ mã xác thực JavaScript giữa máy khách và máy chủ. Đừng viết xác nhận đầu vào của bạn hai lần.


Tôi sẽ xem Rhino. Nếu nó có thể tích hợp bằng cách nào đó với xác thực mẫu Spring MVC, thì tốt hơn nhiều.
mdrg

7

• Tầng thứ 3 (lớp dữ liệu / DAL / DAO): không bao giờ tin rằng cần có nhiều xác thực ở đây, vì chỉ có lớp doanh nghiệp được truy cập dữ liệu (có thể xác thực trong một số trường hợp như "param2 không được rỗng nếu param1 là đúng") .

Điều đó là sai. Nơi quan trọng nhất để có xác nhận là trong chính cơ sở dữ liệu. Dữ liệu hầu như luôn bị ảnh hưởng bởi nhiều hơn ứng dụng (ngay cả khi bạn nghĩ rằng nó sẽ không bị ảnh hưởng) và tốt nhất là không có trách nhiệm khi không đưa các điều khiển thích hợp vào cơ sở dữ liệu. Có nhiều sự mất tính toàn vẹn dữ liệu từ một quyết định không làm điều này hơn bất kỳ yếu tố nào khác. Tính toàn vẹn dữ liệu rất quan trọng đối với việc sử dụng lâu dài cơ sở dữ liệu. Tôi chưa bao giờ thấy bất kỳ cơ sở dữ liệu nào không thực thi các quy tắc toàn vẹn ở cấp cơ sở dữ liệu có chứa dữ liệu tốt (và tôi đã thấy dữ liệu trong hàng ngàn cơ sở dữ liệu theo nghĩa đen).

Anh ấy nói điều đó tốt hơn tôi: http://softarch.97things.oreilly.com/wiki/index.php/Database_as_a_Fortress


Tôi đồng ý đến phần cuối cùng với bài viết này, tôi đoán tôi đã không làm rõ bản thân mình ở phần này. Tôi cập nhật câu hỏi với thông tin chi tiết. Cảm ơn!
mdrg

2

Tất cả những điều trên đưa ra giả định rằng các nhà phát triển và nhà bảo trì là hoàn hảo và viết mã hoàn hảo luôn chạy hoàn hảo. Các bản phát hành phần mềm trong tương lai biết về tất cả các giả định bạn đưa ra và chưa bao giờ ghi lại, và người dùng và tin tặc đưa dữ liệu vào hệ thống theo cách bạn không bao giờ tưởng tượng được.

Chắc chắn, quá nhiều xác nhận là một điều xấu, nhưng giả sử các chương trình, mạng và hệ điều hành là hoàn hảo, tin tặc sẽ không vượt qua được tường lửa của bạn, một DBA sẽ không "chỉnh" thủ công cơ sở dữ liệu có thể tồi tệ hơn.

Vẽ các vòng tròn ranh giới xung quanh mọi thứ, xác định các chế độ thất bại mà nó bảo vệ chống lại và thực hiện một mức độ thích hợp để kiểm tra ranh giới đó. Chẳng hạn, cơ sở dữ liệu của bạn sẽ không bao giờ thấy dữ liệu không hợp lệ, nhưng làm thế nào nó có thể xảy ra và nếu nó xảy ra thì sao? Ai là người dùng của bạn, chi phí của sự thất bại là gì?

Nghiên cứu các mô hình an ninh thế giới vật lý, bảo mật nên ở trong các lớp, giống như một củ hành. Một bức tường dày được coi là an ninh kém. Xác nhận dữ liệu nên được xem xét theo cùng một cách.


1

Hai quy tắc ngắn, chung để xác nhận:

Nếu bạn định gọi bất cứ thứ gì không đảm bảo, nó sẽ trả về một cái gì đó (lỗi, ngoại lệ) để cho bạn biết về đầu vào không hợp lệ theo cách bạn có thể gửi lại cho người gọi, xác thực nó.

Nếu bạn sẽ làm bất cứ điều gì khác với dữ liệu (đưa ra quyết định, làm toán, lưu trữ dữ liệu, v.v.), hãy xác thực nó.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.