2012-08-31 8 views
9

Sto testando la propagazione di JAAS Subject con un custom Principal da un client EJB autonomo in esecuzione su un runtime Java non elaborato su un server JavaEE. Ho come target sia le implementazioni di JBoss che quelle di WebSphere.Come propagare JAAS Subject quando si chiama un EJB remoto (RMI su IIOP) da un client puro

Secondo this forum thread mi aspettavo che avrebbe funzionato facilmente con JBoss.

Ecco il mio EJB client di codice frammento di codice:

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); 

codice lato server è:

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

A dire il vero, anche se è il comportamento di default, ho aggiunto questa sezione al mio ejb-jar.xml session bean:

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

mio session bean non è protetto da un y ruolo.

In base a this IBM WebSphere infocenter section, ho anche abilitato la proprietà di sistema com.ibm.CSI.rmiOutboundPropagationEnabled=true.

Tecnicamente parlando, la chiamata di servizio funziona correttamente su JBoss o WebSphere. Ma l'oggetto JAAS che include il mio principal personalizzato creato sul client non viene propagato al server. Ovviamente, lo Subject scaricato prima della creazione del contesto JNDI e della chiamata EJB è OK.

corro la stessa versione runtime Java per server e client (IBM java6 SR9 FP2 ...), MyPrincipal classe serializzabile è disponibile nel classpath del server (AppServer/lib/ext per WebSphere, server/default/lib per JBoss)

WebSphere discariche:

[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 discariche:

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

di sicuro, ho perso una sorta di s magici Pell. Sai quale?

+0

Quindi? Ho già scritto con successo un LoginModule personalizzato per il supporto di WebSphere e Tivoli PDPrincipal, ho configurato LoginModule in JBoss per abilitare Kerberos SPNEGO su HTTP ... Sicuramente mi trovo a mio agio con JAAS e altre cose in giro. Chiedo solo se ho sbagliato pensando che dovrebbe funzionare ... prima di aprire il codice sorgente JBoss per verificare –

+1

Allora sei più esperto di me;) (Ho giocato con LoginModules, autenticazione personalizzata, inoltro principale su RMI-IIOP/CORBA in Glassfish 2.x, e questo è sempre stato molto complicato. In definitiva, l'abbiamo gestito a livello di applicazione da solo) scoraggeremo qualsiasi forma usando questi standard per l'autenticazione username/password. Se il punto è quello di integrare con Kerberos e fornire il single sign-on, questo potrebbe essere ancora il modo migliore per andare! Scusa, non posso aiutare di più. – ewernli

+0

Se di fatto, l'obiettivo è di non riuscire a utilizzare Kerberos con WebSphere nel nostro specifico contesto: http://stackoverflow.com/questions/10518057/how-to-enable-kerberos-authentication-for-remote-ejb- call-on-websphere –

risposta

3

Sospetto che non sia stata abilitata la sicurezza sul server WAS. Poiché la sicurezza non è abilitata e non hai effettuato l'autenticazione in WAS, non ci sono credenziali. Quindi la tua chiamata a getCallerPrincipal sta tornando UNAUTHENTICATED.

Se si attiva la sicurezza dell'applicazione in WAS, è necessario autenticarsi tramite CSIv2 protocol. La creazione del tuo soggetto JAAS in un client standalone non lo farà. Se potesse, allora chiunque potrebbe creare una credenziale "hey, it's me" e accedere a qualsiasi EJB remoto che volevano.

Il codice funzionerà sul server allegando il soggetto al thread di esecuzione in esecuzione. Affluenti soggetti/credenziali attraverso il filo richiede un protocollo per effettuare la serializzazione delle informazioni soggetto e garantire la fiducia del partito affermando l'identità nella credenziale. Da un client standalone, WAS accetta le informazioni dell'utente sotto forma di autorizzazione di base, LTPA e kerberos. Questo può essere configurato su una configurazione CSIv2 in entrata all'interno della console di amministrazione. È documentato nel collegamento dell'Info Center che ho fatto riferimento in precedenza.

È roba divertente. In bocca al lupo.

+0

Grazie e hai ragione, è richiesto un LoginModule specifico per JBoss. Per la propagazione di WebSphere non è la parte più semplice, quindi decido di personalizzare la catena di autenticazione con un LoginModule personalizzato e quindi il client JVM deve essere configurato con sas.client.properties in com.ibm.CORBA.ConfigURL. In ogni caso, i metodi EJB devono essere protetti. –

0

probabilmente questo ti aiuterà con il prezzo di utilizzare classi websphere proprietarie. come mi ricordo, WebSphere non propaga le JAA chiamante-soggetto, questo è tipico di 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; 
    } 


} 

vedi anche: Getting the caller subject from the thread for JAAS e Getting the RunAs subject from the thread

+0

Ho rinunciato fino a che la sicurezza dovrebbe essere abilitata "globalmente" in Websphere per funzionare, e l'autenticazione Kerberos potrebbe essere necessaria per ottenere SSO senza chiedere agli utenti di autenticarsi quando la sicurezza è abilitata. Come soluzione, ho progettato un'implementazione di ORB PortableInterceptor per aggiungere i messaggi IIOP con il mio contesto personale in cui ho memorizzato il nome di accesso dell'utente. –

Problemi correlati