2012-10-25 37 views
5

Tôi đang nghiên cứu JAAS và tôi đang triển khai một ví dụ đơn giản để sử dụng trong một ứng dụng web sử dụng Tomcat với JaasRealm.Tomcat-Jaas - Làm thế nào để lấy chủ đề?

Bây giờ vấn đề của tôi là tôi không biết cách lấy chủ đề vì mã như Subject subject = Subject.getSubject(AccessController.getContext()); luôn trả về giá trị rỗng.

Tôi đang sử dụng Tomcat 7.0.27. Có điều gì tôi đã bỏ lỡ? Trong các điều khoản khác làm cách nào tôi có thể quản lý ủy quyền trong Java EE với JAAS? Ví dụ như làm thế nào tôi có thể thực hiện một hành động trong bối cảnh an toàn của JAAS?

+0

Hãy chắc chắn rằng vương quốc của bạn được sử dụng cho webapp của bạn, sau đó bạn có thể thử Servlets API của 'HttpServletRequest.getUserPrincipal() ' –

+0

tôi biết điều đó và nó hoạt động, nhưng tôi cần phải lấy đối tượng để có được cũng roleprincipal – sasaman85

Trả lời

8

tôi biết điều đó và nó hoạt động, nhưng tôi cần phải lấy đối tượng để có được cũng roleprincipal

Thật không may, nó không hoạt động như thế trong Java EE. Chủ đề JAAS chỉ là một "túi hiệu trưởng", và cái nào đại diện cho người sử dụng/người gọi chính và/hoặc vai trò hiệu trưởng không được chuẩn hóa. Mỗi container khác làm những việc khác nhau ở đây. Các Javadoc for Tomcat's JAASRealm mô tả này và giải thích các quy ước Tomcat cụ thể (tôi nhấn mạnh):

các JAAS Thông số kỹ thuật mô tả các kết quả của một đăng nhập thành công như một javax.security.auth.Subject dụ , có thể chứa số không hay nhiều đối tượng java.security.Principal trong giá trị trả về của phương thức Subject.getPrincipals(). Tuy nhiên, không cung cấp hướng dẫn trên cách phân biệt Nguyên tắc mô tả người dùng cá nhân (và do đó thích hợp để trả về giá trị request.getUserPrincipal() trong ứng dụng web) từ (các) hiệu trưởng mô tả vai trò được ủy quyền cho người dùng này. Để duy trì càng nhiều độc lập càng tốt từ cơ bản LoginMethod thực hiện thực hiện bởi JAAS, chính sách sau đây được thực hiện bởi Realm này: [...]

Bên cạnh đó, từ một môi trường Java EE bạn hiếm khi thậm chí có quyền truy cập vào Chủ đề JAAS, thường không thông qua các phương thức cụ thể của nhà cung cấp. JAAS cách xa tiêu chuẩn phổ quát mà bạn cho rằng đó là, đặc biệt là khi nó liên quan đến Java EE.

Điều duy nhất bạn có thể truy cập theo cách di động là người gọi chính và vai trò liên kết với nó, nhưng ngay cả những người không phải là người gọi chính xác mà mô-đun đăng nhập JAAS của bạn được xây dựng.

Ví dụ JBoss AS, sao chép hiệu trưởng này một vài lần bằng cách sử dụng các lớp riêng của nó. Vì vậy, nếu mô-đun JAAS của bạn lưu trữ kaz.zak.FooPrincipal vào Chủ đề cho người dùng/người gọi chính, thì HttpServletRequest#getUserPrincipal() có thể trả lại org.jboss.security.SimplePrincipal. Điều duy nhất được đảm bảo là getName() trên trường hợp đó sẽ trả về cùng một chuỗi.

Đối với một số nền thêm về chủ đề này:

Nguồn cuối cùng về cơ bản nói điều tương tự, trong cách diễn đạt khác nhau;

Mặc dù nó có thể sử dụng JAAS trong Tomcat như một cơ chế xác thực (JAASRealm), sự linh hoạt của các khuôn khổ JAAS bị mất khi người dùng được xác thực. Điều này là do các hiệu trưởng là được sử dụng để biểu thị các khái niệm "người dùng" và "vai trò" và không còn là có sẵn trong ngữ cảnh bảo mật mà webapp được thực hiện. Kết quả của xác thực chỉ khả dụng qua request.getRemoteUser() và request.isUserInRole().

Điều này làm giảm khung công tác JAAS cho mục đích ủy quyền cho hệ thống người dùng/vai trò đơn giản mất kết nối với Chính sách bảo mật Java .

+0

Cảm ơn , nhưng tôi không hiểu cách kết nối ủy quyền Jaas với tomcat (sử dụng doas etc) – sasaman85

+0

Thông thường bạn sẽ viết một mô-đun đăng nhập cụ thể cho container, sử dụng JAAS hoặc bất kỳ công nghệ nào bạn muốn và hoàn thành hợp đồng của container. Khi bạn đăng nhập theo chương trình (HttpServletRequest # login) HOẶC truy cập một tài nguyên được bảo vệ, việc xác thực sẽ được thực hiện và thùng chứa sẽ nhận thức được điều này. Thông qua các ràng buộc trong các tài nguyên web.xml () như các trang web được bảo mật. Ủy quyền xảy ra bằng cách so sánh các vai trò được yêu cầu với vai trò mà người dùng đã xác thực có. Nếu trận đấu, người dùng được ủy quyền. –

+0

p.s. JAASRealm của Tomcat là một nguyên mẫu của JASPIC. Tôi không có kinh nghiệm với điều này, nhưng nó âm thanh như một cái gì đó là một chéo giữa hồ sơ Servlet và hồ sơ cầu. –

0

Để truy xuất Chủ đề, chúng tôi có thể sử dụng kết hợp LoginModule và Valve. Thực tế là van được gọi trước khi xác thực đá trong đang giúp chúng tôi ở đây. Khi van được gọi nó đặt phiên trong ThreadLocal (tương tự như cách JBOSS lưu yêu cầu trong ThreadLocal) và sau đó khi LoginModule.commit() được gọi nó sẽ lưu đối tượng vào phiên.

Để cấu hình tiện ích này mã biên dịch cho các lớp học dưới đây để một cái bình và đặt nó dưới $ CATALINA_BASE/lib/

package my.test; 

import java.io.IOException; 
import java.util.Map; 

import javax.security.auth.Subject; 
import javax.security.auth.callback.CallbackHandler; 
import javax.security.auth.login.LoginException; 
import javax.security.auth.spi.LoginModule; 
import javax.servlet.ServletException; 

import org.apache.catalina.Session; 
import org.apache.catalina.connector.Request; 
import org.apache.catalina.connector.Response; 
import org.apache.catalina.valves.ValveBase; 

/** 
* Use following class to retrieve subject in your HTTPServlet when using Tomcat. 
*/ 
public class ContainerServices extends ValveBase implements LoginModule { 

    // Key to revtieve subject from session. 
    public static final String SUBJECT_KEY = 
     "javax.security.auth.Subject.container"; 

    /** 
    * Session for current thread. 
    */ 
    static InheritableThreadLocal<Session> sessionHolder = 
     new InheritableThreadLocal<Session>(); 

    // JAAS Subject being authenticated. 
    private Subject subject; 

    // Invoke the value. 
    public void invoke(Request request, Response response) throws IOException, 
      ServletException { 

     sessionHolder.set(request.getSessionInternal(true)); 

     try { 
      // Next in the invocation chain 
      getNext().invoke(request, response); 
     } finally { 
      sessionHolder.remove(); 
     } 
    } 

    // Initialize the login module 
    public void initialize(Subject subject, CallbackHandler callbackHandler, 
     Map<String, ?> sharedState, Map<String, ?> options) { 
     this.subject = subject; 
    } 

    // Store subject to session. 
    public boolean commit() throws LoginException { 

     Session session = sessionHolder.get(); 

     if (session != null) { 
      session.getSession().setAttribute(ContainerServices.SUBJECT_KEY, subject); 
     } 

     return true; 
    } 

    // not used 
    public boolean abort() throws LoginException { 
     return false; 
    } 

    // not used 
    public boolean login() throws LoginException { 
     return true; 
    } 

    // not used 
    public boolean logout() throws LoginException { 
     return true; 
    } 
} 

Trong $ CATALINA_BASE/conf/server.xml thêm sau cấu hình Van như đứa trẻ yếu tố của.

<Valve className="my.test.ContainerServices" /> 

Trong file jaas.config thêm lớp giống như LoginModule.

DummyAppLogin { 
    my.test.ContainerServices required debug=true; 
    my.test.DummyAppLoginModule required debug=true; 
}; 

Bây giờ sau khi bạn đăng nhập, chứng thực Chủ đề có thể được lấy ra sử dụng tiếp theo.

session.getAttribute(ContainerServices.SUBJECT_KEY); 
Các vấn đề liên quan