Phản xạ có phải là một bất lợi vì các biến riêng tư không thể bị hạn chế?


14

Công cụ privatesửa đổi được sử dụng để hạn chế quyền truy cập bên ngoài lớp, nhưng sử dụng phản xạ các lớp khác có thể truy cập các phương thức và trường riêng. Vì vậy, tôi tự hỏi làm thế nào chúng ta có thể hạn chế khả năng tiếp cận nếu nó là một phần của yêu cầu.


2
Mã tin cậy thấp không thể sử dụng phản ánh riêng tư (ít nhất là không phải trên các hội đồng khác, tôi quên các chi tiết). Mã tin cậy đầy đủ có thể chỉ cần sử dụng con trỏ để bỏ qua mọi hạn chế trong quy trình.
CodeInChaos

55
Công cụ sửa đổi truy cập riêng chủ yếu tồn tại để nói với các lập trình viên "không sử dụng điều này từ bên ngoài lớp và nếu bạn thực sự làm như vậy, đừng phàn nàn nếu phiên bản tiếp theo phá vỡ mã của bạn" không phải là tính năng bảo mật được thi hành nghiêm ngặt.
CodeInChaos


4
Người dùng cũng có thể chỉ cần vá mã của bạn để làm bất cứ điều gì họ muốn. Với một ngoại lệ một phần cho DRM (không đủ mạnh để cung cấp sự bảo vệ lâu dài), bất kỳ ai có quyền truy cập vào ứng dụng của bạn (mã nhị phân hoặc mã nguồn) đều có thể làm bất cứ điều gì với nó.
Brian

6
Đây không phải là một câu hỏi cụ thể về ngôn ngữ? Sự phản chiếu hoạt động khác nhau trong các ngôn ngữ khác nhau. Tôi tự hỏi nếu câu hỏi này nên có một thẻ cho Java hoặc cái gì khác.
Wayne Conrad

Câu trả lời:


54

Mục đích của các sửa đổi truy cập là để thông báo cho các nhà phát triển viết mã về giao diện chung của một lớp. Chúng không phải là một biện pháp bảo mật theo bất kỳ cách nào và chúng không thực sự che giấu hoặc bảo mật bất kỳ thông tin nào.


33
Điều này là không đúng sự thật. Trích dẫn Eric Lippert , "Bộ sửa đổi truy cập trong CLR là các tính năng bảo mật. Các quy tắc truy cập được kết hợp chặt chẽ với các hệ thống an toàn và bảo mật loại." Trong C #, Reflection chỉ có sẵn cho mã chạy hoàn toàn tin cậy. Điều này không (và không thể) áp dụng cho người dùng độc hại của hệ thống đang chạy mã. Tuy nhiên, nó không áp dụng cho các trình cắm thêm độc hại.
Brian

5
@Brian Trường hợp vấn đề mà Brian đề cập có liên quan là khi một hệ thống cho phép mã của bên thứ ba chạy mà không hoàn toàn tin tưởng vào nó. Ví dụ bao gồm hộp cát trình duyệt (ví dụ: applet bị ghét nhiều), công cụ ứng dụng googleAzure . Sẽ thật ngu ngốc khi Azure cho phép mã không tin cậy khám phá các chi tiết của các thư viện cốt lõi của nền tảng.
JimmyJames

3
@Brian Điều đó không chính xác 100% - có một số thao tác phản chiếu bạn có thể thực hiện trong mã tin cậy một phần; nó chỉ không cho phép bạn làm những việc như truy cập các lĩnh vực riêng tư.
Luaan

1
@Brian Cho đến khi ai đó tìm thấy lỗ hổng hoặc kỹ thuật xã hội cho phép họ bỏ qua các hạn chế. Không có điểm nào trong việc cố gắng sử dụng chúng theo cách đó. Đó không phải là mục đích chính của họ.
jpmc26

31

Để trích dẫn Herb Sutter về quyền truy cập lớp :

"Vấn đề ở đây là bảo vệ chống lại Murphy so với bảo vệ chống lại Machiavelli ... nghĩa là bảo vệ chống lại sự lạm dụng vô tình (mà ngôn ngữ này làm rất tốt) so với việc bảo vệ chống lại sự lạm dụng có chủ ý (điều này thực sự là không thể). một lập trình viên muốn đủ mạnh để lật đổ hệ thống, anh ta sẽ tìm ra cách "


2
những lúc bạn cần sandbox mã không tin cậy, nhưng đó là một nhiệm vụ khó khăn. Bảo vệ chống lỗi (Murphy) là trường hợp phổ biến hơn nhiều.
Paul Draper

#define private public(bỏ qua rằng đó thực sự là Hành vi không xác định) và voila Tôi có toàn quyền truy cập từ bên ngoài vào phần bị hạn chế trong các lớp học của bạn.
bolov

Bảo vệ chống lại lạm dụng có chủ ý có thể về mặt lý thuyết là không thể nhưng thực sự có thể, bằng cách làm cho việc lạm dụng đủ khó khăn mà nó rất hiếm khi xảy ra. Điều quan trọng là phải rõ ràng về điều đó. Mặt khác, hoàn toàn không thể sử dụng phần mềm trong các tình huống như thiết bị y tế quan trọng đến tính mạng.
MarkJ

@MarkJ. Nhận xét của Herb Sutter là về sự lạm dụng có chủ ý của nhà phát triển, người đã viết lớp này ngay từ đầu và có lẽ là đồng đội của anh ta. Tôi không nghĩ có một cách để ngăn chặn sự lạm dụng đó bằng các tính năng ngôn ngữ.
Nemanja Trifunovic

Tôi nghĩ @bolov đóng thế là phụ thuộc ngôn ngữ. Mặc dù các bộ tiền xử lý C / C ++ có thể cho phép bạn thoát khỏi điều đó, nhưng bất cứ điều gì không có chúng có thể sẽ gây ra lỗi "không thể sử dụng các từ dành riêng trong lỗi #define".
Dan Neely

10

Không, đây thực sự là một lợi thế quan trọng. Đơn giản là vì một số nhà phát triển đã không nghĩ rằng bất kỳ ai cũng cần quyền truy cập vào một số trạng thái nội bộ không có nghĩa là sẽ không có trường hợp sử dụng hợp pháp nào xuất hiện. Trong những trường hợp này, sử dụng Reflection để thực hiện phẫu thuật trên một đối tượng có thể là biện pháp cuối cùng. Tôi đã phải sử dụng kỹ thuật này hơn một lần.


Nói cách khác, đó là một cách để phá vỡ một API có khả năng bị hỏng - cho dù do yêu cầu không đầy đủ hoặc thực hiện không đầy đủ.
Phục hồi Monica

4

Bạn hạn chế khả năng truy cập thậm chí nhiều hơn bằng cách tăng thêm một cấp: môi trường thực thi.

Không phải tất cả các ngôn ngữ đều có khái niệm này, nhưng ít nhất với Java, bạn có thể sử dụng trình quản lý bảo mật cấm làm cho các trường riêng tư có thể truy cập được. Bạn có thể tự cài đặt trình quản lý bảo mật trong thời gian chạy hoặc thêm chính sách bảo mật trong tệp jar sau đó được niêm phong để ngăn sửa đổi.

Thông tin thêm về cách thực hiện điều này trong Java: Reflection Security


3

Bạn đang nói về sự phản ánh nào?

Trong nhiều hệ thống phản chiếu, đóng gói tránh né là một khả năng rõ ràng mà mã của bạn cần có và theo mặc định không có.

Nếu bạn lo lắng về việc đóng gói, giải pháp đơn giản là không sử dụng hệ thống phản chiếu không bảo tồn nó.


3

Trong Python, không có sửa đổi truy cập. Quy ước là tiền tố bởi một dấu gạch dưới các phương thức và các biến không được dự kiến ​​sẽ được truy cập từ bên ngoài lớp. Liệu về mặt kỹ thuật có ngăn bạn truy cập vào trường như vậy từ lớp bên thứ ba không? Không có gì; nhưng nếu bạn làm thế, bạn chỉ có một mình và bạn có nguy cơ phá vỡ thứ gì đó, mà không thể đổ lỗi cho lớp khác.

Trong C #, các công cụ sửa đổi truy cập tồn tại, nhưng chúng chỉ là một quy ước mà một trình biên dịch được thi hành bởi trình biên dịch, nhưng vẫn là một quy ước. Điều này có nghĩa là về mặt kỹ thuật, người ta vẫn có thể truy cập và thay đổi các biến riêng tư, thông qua Reflection hoặc bằng cách giả mạo trực tiếp bộ nhớ (giống như các huấn luyện viên trò chơi làm). Hậu quả hoàn toàn giống nhau: nếu các biến của lớp bạn bị thay đổi thông qua Reflection từ một lớp khác hoặc thông qua việc giả mạo bộ nhớ bởi một ứng dụng khác và nó phá vỡ thứ gì đó trong lớp của bạn, đó không phải là lỗi của bạn.

Lưu ý rằng điều này, rõ ràng, tạo ra các vấn đề bảo mật trong đó bên thứ ba có thể truy cập dữ liệu của bạn ; một cái gì đó dẫn đến các biến thể được mã hóa của một chuỗi và các cấu trúc dữ liệu tương tự. Nhưng việc bảo vệ mã của bạn khỏi việc sử dụng như vậy có liên quan nhiều hơn đến các hạn chế truy cập ở cấp độ mã và hệ điều hành và không liên quan gì đến Reflection per se.


2
Lưu ý rằng trong C #, chỉ có mã đáng tin cậy hoàn toàn có thể phản ánh các thành viên riêng. Viết trực tiếp để xử lý bộ nhớ vẫn hoạt động, nhưng khó hơn so với mã gốc.
Luaan
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.