2012-08-31 14 views
9

Estoy probando la propagación de JAAS Subject con un custom Principal desde un cliente EJB independiente que se ejecuta en un servidor Java Java en tiempo de ejecución sin procesar. Me estoy enfocando en las implementaciones de JBoss y WebSphere.Cómo propagar el sujeto JAAS al llamar a un EJB remoto (RMI sobre IIOP) desde un cliente puro

Según this forum thread esperaba que funcionara con JBoss fácilmente.

Aquí es mi EJB código de código de cliente fragmento:

Subject subject = new Subject(); 
Principal myPrincipal = new MyPrincipal("me I myself"); 
subject.getPrincipals().add(myPrincipal); 

PrivilegedExceptionAction<String> action = new PrivilegedExceptionAction<String>() { 
    public String run() throws Exception { 
      String result; 
      System.out.println("Current Subject: " + Subject.getSubject(AccessController.getContext())); 
      InitialContext ic = new InitialContext(); 
      Business1 b = (Business1) ic.lookup("StatelessBusiness1"); 
      result = b.getNewMessage("Hello World"); 
      return result; 
     } 
    }; 

result = subject.doAs(subject, action); 
System.out.println("result "+result); 

código del lado del servidor es:

public String getNewMessage(String msg) { 
    System.out.println("getNewMessage principal: " + sessionContext.getCallerPrincipal()); 
    System.out.println("Current Subject: " + Subject.getSubject(AccessController.getContext())); 
    return "getNewMessage: " + msg; 
} 

Para estar seguros, incluso si es el comportamiento por defecto, he añadido esta sección a mi ejb-jar.xml bean de sesión:

<security-identity> 
    <use-caller-identity/> 
</security-identity> 

mi bean de sesión no está protegido por una y rol

De acuerdo con this IBM WebSphere infocenter section, también he habilitado la propiedad del sistema com.ibm.CSI.rmiOutboundPropagationEnabled=true.

Técnicamente hablando, la llamada de servicio funciona correctamente en JBoss o WebSphere. Pero el Sujeto JAAS que incluye mi principal personalizado creado en el cliente no se propaga al servidor. O por supuesto, el Subject volcado justo antes de la creación del contexto JNDI y la llamada EJB está bien.

que ejecuta la misma versión de tiempo de ejecución Java para servidor y el cliente (IBM java6 SR9 FP2 ...), MyPrincipal clase serializable está disponible en ClassPath servidor (AppServer/lib/ext para WebSphere, server/default/lib para JBoss)

WebSphere vertederos:

[8/31/12 11:56:26:514 CEST] 00000024 SystemOut  O getNewMessage principal: UNAUTHENTICATED 
[8/31/12 11:56:26:515 CEST] 00000024 SystemOut  O Current Subject: null 

JBoss vertederos:

12:30:20,540 INFO [STDOUT] getNewMessage principal: anonymous 
12:30:20,540 INFO [STDOUT] Current Subject: null 

Por supuesto, me he perdido algún tipo de s mágicas pell. Sabes cuál ?

+0

Así? Ya he escrito con éxito un LoginModule personalizado para soporte de WebSphere y Tivoli PDPrincipal, he configurado LoginModule en JBoss para habilitar Kerberos SPNEGO sobre HTTP ... Definitivamente estoy cómodo con JAAS y otras cosas. Solo pregunto si me equivoco al pensar que debería funcionar ... antes de abrir el código fuente de JBoss para verificar –

+1

Entonces tienes más experiencia que yo;) (Jugué con LoginModules, autenticación personalizada, reenvío del principal sobre RMI-IIOP/CORBA en Glassfish 2.x, y eso siempre ha sido muy complicado. En última instancia, lo manejamos nosotros mismos a nivel de aplicación) Desanimaría a cualquier persona que use estos estándares para la autenticación de nombre de usuario/contraseña. Si el objetivo es integrar Kerberos y proporcionar un inicio de sesión único, ¡esa podría ser la mejor manera de hacerlo! Lo siento, no puedo ayudar más. – ewernli

+0

De hecho, el objetivo es evitar el uso de Kerberos con WebSphere en nuestro contexto específico: http://stackoverflow.com/questions/10518057/how-to-enable-kerberos-authentication-for-remote-ejb- call-on-websphere –

Respuesta

3

Sospecho que no tiene la seguridad habilitada en el servidor WAS. Como la seguridad no está habilitada y no se autenticó en WAS, no hay credencial. Por lo tanto, su llamada al getCallerPrincipal está regresando SIN APLICAR.

Si activa la seguridad de la aplicación en WAS, tendrá que autenticarse a través del CSIv2 protocol. Crear su propio tema JAAS en un cliente independiente no lo hará. Si fuera posible, cualquiera podría crear una credencial de "eh, soy yo" e iniciar sesión en cualquier EJB remoto que quisieran.

Su código funcionará en el servidor adjuntando el asunto al hilo de ejecución en ejecución. El flujo de temas/credenciales a través del cable requiere un protocolo para efectuar la serialización de la información del sujeto y garantizar la confianza de la parte que afirma la identidad en la credencial. Desde un cliente independiente, WAS acepta información de usuario en forma de autorización básica, LTPA y kerberos. Esto se puede configurar en una configuración CSIv2 entrante dentro de la consola de administración. Está documentado en el enlace del Centro de información al que hice referencia anteriormente.

Es algo divertido. Buena suerte.

+0

Gracias y tienes razón, se requiere un LoginModule específico para JBoss. Para la propagación de WebSphere no es la parte más fácil, entonces decido personalizar la cadena de autenticación con un LoginModule personalizado y luego la JVM del cliente debe configurarse con sas.client.properties en com.ibm.CORBA.ConfigURL. En cualquier caso, los métodos EJB deben estar seguros. –

0

probablemente esto le ayudará con el precio para usar websphere-classes propietarias. como recuerdo, WebSphere no propaga la llama jaas-sujeto, esto es típico de IBM

package foo.bar; 
import java.util.HashMap; 
import java.util.Iterator; 
import java.util.List; 
import java.util.Map; 
import java.util.Set; 
import javax.security.auth.Subject; 
import javax.security.auth.login.CredentialExpiredException; 
import org.apache.log4j.Logger; 
import com.ibm.websphere.security.WSSecurityException; 
import com.ibm.websphere.security.auth.CredentialDestroyedException; 
import com.ibm.websphere.security.auth.WSSubject; 
import com.ibm.websphere.security.cred.WSCredential; 

public class IdentityHelper 
{ 
    private static final Logger log = Logger.getLogger(IdentityHelper.class); 
    private static final String CLASS_OBJECT = "java.util.HashMap"; 
    private static final String KEY_OBJECT = "java.lang.String"; 
    private static final String VALUE_OBJECT = "java.util.HashSet"; 

    private Subject subject=null; 
    private WSCredential creds; 
    private Set publicCredentials=null; 
    public IdentityHelper(Subject _subject) throws WSSecurityException 
    { 
     if(_subject==null) 
     { 
      IdentityHelper.log.warn("given subject was null, using Caller-Subject or the RunAs-Subject!"); 
      this.subject = WSSubject.getCallerSubject(); 
      if(this.subject==null)this.subject=WSSubject.getRunAsSubject(); 
     } 
     else 
     {   
      this.subject=_subject; 
     } 
     init(); 
    } 
    public IdentityHelper() throws WSSecurityException 
    { 
     this.subject=WSSubject.getRunAsSubject(); 
     if(this.subject==null) 
     { 
      IdentityHelper.log.warn("using Caller-Subject NOT the RunAs-Subject!"); 
      this.subject = WSSubject.getCallerSubject(); 
     } 
     init(); 
    } 

    private void init() throws WSSecurityException 
    { 
     Set<WSCredential> credSet= this.subject.getPublicCredentials(WSCredential.class); 
     //set should contain exactly one WSCredential 
     if(credSet.size() > 1) throw new WSSecurityException("Expected one WSCredential, found " + credSet.size()); 
     if(credSet.isEmpty()) 
     { 
      throw new WSSecurityException("Found no credentials"); 
     } 
     Iterator<WSCredential> iter= credSet.iterator(); 
     this.creds=(WSCredential) iter.next(); 
     this.publicCredentials=this.subject.getPublicCredentials(); 
    } 
    public WSCredential getWSCredential() throws WSSecurityException 
    { 
     return this.creds; 
    } 
    public List<String> getGroups() throws WSSecurityException,CredentialDestroyedException,CredentialExpiredException 
    { 
     WSCredential c = this.getWSCredential(); 
     return c.getGroupIds(); 
    } 
    /** 
    * helper method for obtaining user attributes from Subject objects. 
    * @param subject 
    * @return 
    */ 
    @SuppressWarnings("unchecked") 
    public Map<String, Set<String>> getAttributes() 
    { 
     Map<String, Set<String>> attributes = null; 
     Iterator<?> i = this.subject.getPublicCredentials().iterator(); 
     while (attributes == null && i.hasNext()) 
     { 
      Map<String, Set<String>> tmp = null; 
      Object o = i.next(); 
      if(IdentityHelper.log.isDebugEnabled()) 
      { 
       IdentityHelper.log.debug("checking for attributes (class name): " + o.getClass().getName()); 
      } 
      if(!o.getClass().getName().equals(CLASS_OBJECT)) 
       continue;//loop through 
      tmp = (Map) o; 
      Object tObject = null; 
      Iterator<?> t = null; 
      t = tmp.keySet().iterator(); 
      tObject = t.next(); 
      if(IdentityHelper.log.isDebugEnabled()) 
      { 
       IdentityHelper.log.debug("checking for attributes (key object name): " + tObject.getClass().getName()); 
      } 
      if(!tObject.getClass().getName().equals(KEY_OBJECT)) 
       continue;//loop through 
      t = tmp.values().iterator(); 
      tObject = t.next(); 
      if(IdentityHelper.log.isDebugEnabled()) 
      { 
       IdentityHelper.log.debug("checking for attributes (value object name): " + tObject.getClass().getName()); 
      } 
      if(!tObject.getClass().getName().equals(VALUE_OBJECT)) 
       continue;//loop through 
      attributes = (Map) o; 
     } 
     if (attributes == null) 
     { 
      attributes = new HashMap<String, Set<String>>(); 
     } 
     return attributes; 
    } 
    public Subject getSubject() 
    { 
     return this.subject; 
    } 
    protected Set getPublicCredentials() { 
     return publicCredentials; 
    } 


} 

ver también: Getting the caller subject from the thread for JAAS y Getting the RunAs subject from the thread

+0

Me rendí en lo que respecta a la seguridad debe habilitarse "globalmente" en Websphere para trabajar, y la autenticación Kerberos puede ser necesaria para obtener SSO sin pedirles a los usuarios que se autentiquen cuando la seguridad está habilitada. Como solución alternativa, he diseñado una implementación de ORB PortableInterceptor para adjuntar mensajes IIOP con mi propio contexto donde guardé el nombre de inicio de sesión del usuario. –

Cuestiones relacionadas