2012-10-26 30 views
9

Java Security là chủ đề chính của tôi trong vài tuần qua và tôi lưu trữ như sau:JAAS - Java an ninh theo chương trình trong Java EE 6 (không @DeclareRoles)

  • Tuỳ chỉnh Van Authentificator (extends AuthenticatorBase)
  • Mô-đun Login tùy chỉnh cho JBoss (extends UsernamePasswordLoginModule)
  • Bảo Endpoint (JAX-RS)

vấn đề lớn của tôi là, mà điểm cuối của tôi chỉ làm việc với các chú thích 0.123., nếu tôi không sử dụng nó tôi không thể có được thông qua xác thực. Cụ thể, phương thức AuthenticatorBase.invoke (từ org.apache.catalina.authenticator) gọi phương thức RealmBase.hasResourcePermission và ở đó các vai trò sẽ được kiểm tra.

Vì tôi không sử dụng bất kỳ vai trò được xác định trước nào, kiểm tra sẽ không thành công.

Câu hỏi của tôi: Có cách nào để sử dụng mã như thế:

@Path("/secure") 
@Stateless 
public class SecuredRestEndpoint { 

    @Resource 
    SessionContext ctx; 

    @GET 
    public Response performLogging() { 

     // Receive user information 
     Principal callerPrincipal = ctx.getCallerPrincipal(); 
     String userId = callerPrincipal.getName(); 

     if (ctx.isCallerInRole("ADMIN")) { 
      // return 200 if ok 
      return Response.status(Status.OK).entity(userId).build(); 
     } 
    ... 
    } 
} 

Một số thêm nền: Có là yêu cầu để sử dụng một proxy ngược để xác thực chỉ tên người dùng được chuyển tiếp (X-forward-USER). Đó là lý do tại sao tôi sử dụng lớp Authenticator của riêng tôi và mô-đun Đăng nhập tùy chỉnh (Tôi không có bất kỳ thông tin đăng nhập mật khẩu nào). Nhưng tôi nghĩ rằng vấn đề cũng xảy ra với các phương pháp xác thực chuẩn từ máy chủ ứng dụng chính nó

Trả lời

2

Nếu tôi cho bạn đúng, có hai vấn đề.

  1. Bạn không muốn @DeclareRoles xuất hiện trong mã của mình. Nếu bạn không nhớ sử dụng web.xml, hãy xem xét điều này: http://docs.oracle.com/cd/E19159-01/819-3669/bncbg/index.html

  2. Bạn muốn chỉ sử dụng tên người dùng để truy cập tài nguyên còn lại của bạn, vì tài nguyên còn lại không có mối đe dọa bảo mật, nhưng tại đồng thời nguồn lực còn lại cần phải biết ai đang gọi.

    1. Có nhiều cách để thực hiện việc này. Để xác định người dùng, bạn chỉ cần cung cấp id của người dùng trong yêu cầu http của mình, bảo mật JAAS là quá mức cần thiết. Ví dụ: cung cấp userid theo URI:/user/bob hoặc theo tham số URI như: /user?id=bob.

    2. Nếu bảo mật là bắt buộc (nếu tôi không hiểu sai, bạn đang sử dụng thành phần bảo mật chuẩn của javaee), bạn sẽ cần phải xử lý các vai trò, vì đặc điểm kỹ thuật của java6 có xác thực/ủy quyền dựa trên vai trò trong.

+0

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? –

+0

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

+0

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 –

6

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:

  1. 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.
  2. 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.

+0

Cảm ơn câu trả lời của bạn, rất tiếc là tôi đang đi nghỉ nên tôi không thể trả lời ngay bây giờ. Trong hai tuần, tôi sẽ cố gắng đọc câu trả lời của bạn. Chúc mừng –

+0

Tận hưởng! Tôi ước tôi cũng thế. – rdcrng

+0

Cảm ơn bạn, đó là một nguồn cảm hứng tuyệt vời mặc dù tôi sử dụng Jetty thay vì JBoss. – gouessej

Các vấn đề liên quan