NOTA: la risposta seguente è valida solo per Java EE 5. Come è stato segnalato in una delle altre risposte, Java EE 6 supporta questo. Quindi, se stai utilizzando Java EE 6, non leggere questa risposta, ma leggi l'altra risposta pertinente.
Dalla mia ricerca e dalle risposte a questa domanda la risposta che ho trovato è la seguente: Sebbene JAAS sia un'interfaccia standard, non esiste un modo uniforme per scrivere, distribuire e integrare un Realm + LoginModule JAAS in vari server applicazioni .
Glassfish v2 richiede l'estensione di alcune delle proprie classi interne che implementano LoginModule o Realm. Tuttavia, non è possibile personalizzare l'intero processo di accesso perché molti metodi dell'interfaccia LoginModule sono contrassegnati come finali nella superclasse di Glassfish. Le classi LoginModule e Realm personalizzate devono essere posizionate nel classpath AS (non nell'applicazione) e il dominio deve essere registrato manualmente (nessuna distribuzione da .war possibile).
La situazione sembra essere un po 'migliore per Tomcat, che ti permetterà di codificare completamente il tuo Realm e LoginModule, e poi configurarli nel server delle applicazioni usando il suo JAASRealm (che delegherà il lavoro effettivo alle tue implementazioni di Realm e LoginModule). Tuttavia, anche tomcat non consente la distribuzione del tuo dominio personalizzato dal tuo .war.
Si noti che nessuno degli Application Server che hanno mostrato i miei risultati sembra essere in grado di sfruttare appieno tutti i callback JAAS. Tutti sembrano supportare solo lo schema utente base + password. Se hai bisogno di qualcosa di più complicato, dovrai trovare una soluzione che non sia gestita dal tuo contenitore Java EE.
Per riferimento, e poiché è stato chiesto nei commenti alla mia domanda, ecco il codice che ho scritto per GlassfishV2.
Prima di tutto, ecco l'attuazione Realm:
public class WebserviceRealm extends AppservRealm {
private static final Logger log = Logger.getLogger(WebserviceRealm.class.getName());
private String jaasCtxName;
private String hostName;
private int port;
private String uri;
@Override
protected void init(Properties props) throws BadRealmException, NoSuchRealmException {
_logger.info("My Webservice Realm : init()");
// read the configuration properties from the user-supplied properties,
// use reasonable default values if not present
this.jaasCtxName = props.getProperty("jaas-context", "myWebserviceRealm");
this.hostName = props.getProperty("hostName", "localhost");
this.uri = props.getProperty("uri", "/myws/EPS");
this.port = 8181;
String configPort = props.getProperty("port");
if(configPort != null){
try{
this.port = Integer.parseInt(configPort);
}catch(NumberFormatException nfe){
log.warning("Illegal port number: " + configPort + ", using default port (8181) instead");
}
}
}
@Override
public String getJAASContext() {
return jaasCtxName;
}
public Enumeration getGroupNames(String string) throws InvalidOperationException, NoSuchUserException {
List groupNames = new LinkedList();
return (Enumeration) groupNames;
}
public String getAuthType() {
return "My Webservice Realm";
}
public String getHostName() {
return hostName;
}
public int getPort() {
return port;
}
public String getUri() {
return uri;
}
}
E poi l'attuazione LoginModule:
public class WebserviceLoginModule extends AppservPasswordLoginModule {
// all variables starting with _ are supplied by the superclass, and must be filled
// in appropriately
@Override
protected void authenticateUser() throws LoginException {
if (_username == null || _password == null) {
throw new LoginException("username and password cannot be null");
}
String[] groups = this.getWebserviceClient().login(_username, _password);
// must be called as last operation of the login method
this.commitUserAuthentication(groups);
}
@Override
public boolean commit() throws LoginException {
if (!_succeeded) {
return false;
}
// fetch some more information through the webservice...
return super.commit();
}
private WebserviceClient getWebserviceClient(){
return theWebserviceClient;
}
}
infine, nel regno deve essere legato al LoginModule. Questo viene fatto al livello del file di configurazione JAAS, che in glassfish v2 si trova su yourDomain/config/login.conf. Aggiungere le seguenti righe alla fine di quel file:
myWebserviceRealm { // use whatever String is returned from you realm's getJAASContext() method
my.auth.login.WebserviceLoginModule required;
};
Questo è ciò che ha funzionato per me su glassfish. Ancora una volta, questa soluzione non è portabile tra i server delle applicazioni, ma per quanto posso dire, non esiste una soluzione portatile esistente.
potresti pubblicare un esempio del tuo codice di dominio? –