Kể từ mã của bạn là tĩnh (nghĩa là bạn có một bộ tĩnh của tài nguyên có thể được bảo đảm), tôi không hiểu yêu cầu của bạn cho thêm vai trò an ninh ngoài tăng granularity truy cập. Tôi có thể thấy yêu cầu này trong môi trường mô-đun, trong đó mã không tĩnh, trong trường hợp này bạn sẽ cần hỗ trợ các vai trò bảo mật bổ sung được khai báo bởi các triển khai sau này.
Điều đó nói rằng, tôi đã phải thực hiện một cái gì đó tương tự, một hệ thống bảo mật hỗ trợ:
- thêm (tuyên bố)/loại bỏ vai trò mà không tái triển khai;
- liên kết người dùng với những vai trò đó.
Tôi sẽ mô tả ở mức độ trừu tượng cao những gì tôi đã làm và hy vọng nó sẽ cung cấp cho bạn một số ý tưởng hữu ích.
tắt Thứ nhất, thực hiện một @EJB
, một cái gì đó như thế này:
@Singleton
@LocalBean
public class MySecurityDataManager {
public void declareRole(String roleName) {
...
}
public void removeRole(String roleName) {
...
}
/**
* Here, I do not know what your incoming user data looks like such as:
* do they have groups, attributes? In my case I could determine user's groups
* and then assign them to roles based on those. You may have some sort of
* other attribute or just plain username to security role association.
*/
public void associate(Object userAttribute, String roleName) {
...
}
public void disassociate(Object userAttribute, String roleName) {
...
}
/**
* Here basically you inspect whatever persistence method you chose and examine
* your existing associations to build a set of assigned security roles for a
* user based on the given attribute(s).
*/
public Set<String> determineSecurityRoles(Object userAttribute) {
...
}
}
Sau đó, bạn thực hiện một tùy chỉnh javax.security.auth.spi.LoginModule
. Tôi muốn khuyên bạn nên triển khai nó từ đầu, trừ khi bạn biết container cung cấp triển khai trừu tượng sẽ làm việc cho bạn, nó không cho tôi. Ngoài ra, tôi đề nghị bạn làm quen với những điều sau đây, nếu bạn không phải là, để hiểu rõ hơn những gì tôi nhận được để:
public class MyLoginModule implements LoginModule {
private MySecurityDataManager srm;
@Override
public void initialize(Subject subject, CallbackHandler callbackHandler,
Map<String, ?> sharedState, Map<String, ?> options) {
// make sure to save subject, callbackHandler, etc.
try {
InitialContext ctx = new InitialContext();
this.srm = (MySecurityDataManager) ctx.lookup("java:global/${your specific module names go here}/MySecurityDataManager");
} catch (NamingException e) {
// error logic
}
}
@Override
public boolean login() throws LoginException {
// authenticate your user, see links above
}
@Override
public boolean commit() throws LoginException {
// here is where user roles get assigned to the subject
Object userAttribute = yourLogicMethod();
Set<String> roles = srm.determineSecurityRoles(userAttribute);
// implement this, it's easy, just make sure to include proper equals() and hashCode(), or just use the Jboss provided implementation.
Group rolesGroup = new SimpleGroup("Roles", roles);
// assuming you saved the subject
this.subject.getPrincipals().add(rolesGroup);
}
@Override
public boolean abort() throws LoginException {
// see links above
}
@Override
public boolean logout() throws LoginException {
// see links above
}
}
Để cho phép cấu hình động (tức là tuyên bố vai trò, liên kết người dùng), hãy xây dựng giao diện người dùng t sử dụng cùng @EJB MySecurityDataManager
để CRUD cài đặt bảo mật của bạn mà mô-đun đăng nhập sẽ sử dụng để xác định vai trò bảo mật.
Bây giờ, bạn có thể đóng gói theo cách bạn muốn, chỉ cần đảm bảo rằng MyLoginModule
có thể tra cứu MySecurityDataManager
và bạn triển khai chúng vào vùng chứa. Tôi đã làm việc trên JBoss, và bạn đã đề cập JBoss, do đó, điều này cũng làm việc cho bạn. Việc triển khai mạnh mẽ hơn sẽ bao gồm chuỗi tìm kiếm trong cấu hình của LoginModule, sau đó bạn có thể đọc tại thời điểm chạy từ bản đồ tùy chọn theo phương thức initialize()
. Dưới đây là một cấu hình ví dụ cho JBoss:
<security-domain name="mydomain" cache-type="default">
<authentication>
<login-module flag="required"
code="my.package.MyLoginModule"
module="deployment.${your deployment specific info goes here}">
<module-option name="my.package.MySecurityDataManager"
value="java:global/${your deployment specific info goes here}/MySecurityDataManager"/>
</login-module>
</authentication>
</security-domain>
Tại thời điểm này bạn có thể sử dụng tên miền bảo mật này mydomain
để quản lý an ninh của bất kỳ triển khai khác trong container.
Dưới đây là một kịch bản vài sử dụng:
- Triển khai .WAR mới và gán nó vào miền
mydomain
an ninh. Thewar đi kèm với chú thích bảo mật được xác định trước trong suốt mã của nó. Tuy nhiên, sau khi triển khai, vì vai trò bảo mật được ghi lại đầy đủ, bạn mở giao diện cấu hình của mydomain
mà bạn đã viết và khai báo các vai trò đó, sau đó gán người dùng cho họ. Bây giờ họ có thể đăng nhập.
- Sau một vài tháng triển khai, bạn không còn muốn người dùng có quyền truy cập vào mục đích cụ thể của cuộc chiến. Xóa các vai trò bảo mật liên quan đến phần đó của chiến dịch. Từ số
mydomain
của bạn và không ai có thể sử dụng nó.
Phần tốt nhất, đặc biệt là khoảng # 2 không có triển khai lại.Ngoài ra, không có chỉnh sửa XML để ghi đè lên các thiết lập bảo mật mặc định được khai báo với chú thích (Đó là giả định giao diện của bạn là tốt hơn so với đó).
Chúc mừng! Tôi rất sẵn lòng cung cấp thêm chi tiết cụ thể, nhưng hiện tại, điều này ít nhất sẽ cho bạn biết liệu bạn có cần chúng hay không.
Cảm ơn câu trả lời của bạn: 1. Lý do tại sao tôi không muốn có '@ DeclareRoles' trong mã của tôi là vì nó tĩnh và vai trò có thể thay đổi theo thời gian (bảo trì). 2.1 Tôi không muốn chỉ có tên người dùng trong mã REST. Hãy suy nghĩ về bối cảnh sâu sắc hơn mà tôi không có tên hiện tại và tôi không thể luôn luôn cung cấp cho anh ta. Tôi có thể dễ dàng đọc tham số từ tiêu đề reqeust, nhưng đó không phải là mục tiêu của tôi. 2.2 Tôi muốn có bảo mật JEE với 'SesseionContext' và vai trò người dùng, nhưng tại sao nó phải tĩnh và không chỉ có lập trình? –
Chỉ cần cho câu hỏi "tại sao nó phải là tĩnh và không chỉ có lập trình?" Vai trò là tĩnh vì các ứng dụng, nói chung, không nên tự động tăng các tính năng bảo mật của nó mà không cần triển khai lại. Mặc dù bạn có thể quyết định có chỉ định vai trò trong web.xml hay bean của bạn để bảo trì mã dễ dàng hơn, nhưng tốt hơn không tránh việc triển khai lại mã. – Xiangyu
Thats một điểm tốt và thay đổi nó trong web.xml không phải là một việc lớn (không cần triển khai lại). Tôi chắc chắn sẽ xem xét nó. Từ dự án của tôi, điều quan trọng là không triển khai lại nếu mọi thứ thay đổi, bởi vì nó là mã tùy chỉnh cho một khách hàng không muốn chạm vào mã và cũng không yêu cầu nhà cung cấp làm việc đó mọi lúc. Đó là lý do tại sao tôi đang tìm kiếm một giải pháp cấu hình dễ dàng. Nhưng ngoài ra, tôi nghĩ rằng có một cách để làm phương pháp tiếp cận của tôi và tôi sẽ giữ cho tiền thưởng mở để nhận được càng nhiều phản ứng càng tốt: D –