Question

J'écris une application web java qui ont besoin d'effectuer la connexion par un webservice. Bien sûr, aucun des domaines fournis avec le serveur d'application que je utilise (GlassFish v2) peut faire l'affaire. Je devais donc d'écrire mon propre. Il semble toutefois que la mise en œuvre du domaine que j'ai écrit est complètement lié à Glassfish et ne peut pas être utilisé tel quel dans tous les autres serveurs d'applications.

est-il un moyen standard ou largement pris en charge pour mettre en œuvre un royaume personnalisé? Est-il de toute façon possible de déployer ce royaume d'un .war, ou faut-il toujours être chargé à partir du propre chemin de classe serveur?

Était-ce utile?

La solution

NOTE: La réponse est inférieure uniquement valable pour Java EE 5. Comme il a été porté à mon attention dans l'une des autres réponses, Java EE 6 ne supporte cela. Donc, si vous utilisez Java EE 6, ne lisez pas cette réponse, mais lisez l'autre réponse pertinente.

De mes propres recherches et des réponses à cette question la réponse que je trouve est la suivante: Bien que JAAS est une interface standard, il n'y a pas de façon uniforme à écrire, déployer et intégrer un royaume JAAS + LoginModule dans divers serveurs d'applications.

Glassfish v2 vous oblige à étendre certaines de ses propres classes internes qui mettent en œuvre LoginModule ou Realm eux-mêmes. Vous pouvez cependant pas personnaliser l'ensemble du processus de connexion, car de nombreuses méthodes de l'interface LoginModule sont marqués finale dans la superclasse de Glassfish. Les loginModule personnalisés et les classes Realm doivent être placés dans l'AS classpath (pas de l'application), et le domaine doit être enregistré manuellement (pas de déploiement de la possible .war).

La situation semble être un peu mieux pour Tomcat, qui laissera vous codez votre propre royaume et LoginModule complètement, puis les configurer dans le serveur d'application en utilisant son propre JAASRealm (qui déléguera le travail réel à vos implémentations de Realm et LoginModule). Cependant, même ne tomcat permet pas le déploiement de votre domaine personnalisé de votre .war.

Notez qu'aucun des serveurs d'applications qui ont montré mes résultats semblent être en mesure de profiter pleinement de toutes les JAA Callbacks. Tous semblent soutenir que le système de nom d'utilisateur + mot de passe de base. Si vous avez besoin quelque chose de plus compliqué que cela, alors vous aurez besoin de trouver une solution qui ne soit pas géré par votre conteneur Java EE.

Pour référence, et parce qu'il a été demandé dans les commentaires à ma question, voici le code que j'ai écrit pour glassfishv2.

Tout d'abord, voici la mise en œuvre du Royaume:

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

Et puis la mise en œuvre du 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;
}
}

enfin, dans le domaine doit être lié à la LoginModule. Cela se fait au niveau du fichier de configuration JAAS, qui GlassFish v2 est au yourDomain / config / login.conf. Ajouter à la fin de ce fichier les lignes suivantes:

myWebserviceRealm { // use whatever String is returned from you realm's getJAASContext() method
    my.auth.login.WebserviceLoginModule required;
};

C'est ce qui a des choses qui travaillent pour moi sur GlassFish. Encore une fois, cette solution n'est pas portables sur les serveurs d'application, mais pour autant que je sache, il n'y a pas de solution portable existante.

Autres conseils

  

est-il un moyen standard ou largement pris en charge pour mettre en œuvre une coutume   Domaine? Est-il de toute façon possible de déployer ce royaume d'un .war ou   t-il toujours besoin d'être chargé à partir du propre chemin de classe serveur?

Il n'y a absolument un moyen standard pour mettre en œuvre un royaume personnalisé, ou en termes plus généraux un module d'authentification personnalisé. Cela peut se faire via le JASPIC / JASPI / JSR 196 SPI / API . JASPIC est une partie intégrante de toute mise en œuvre complète Java EE 6, mais malheureusement pas partie du profil Web Java EE 6.

Cependant, en dépit JASPIC étant une partie de Java EE 6, il est pas pris en charge de façon optimale par les fournisseurs. GlassFish et WebLogic semblent avoir de très bonnes implémentations, JBoss AS et Geronimo sont un peu plus problématique. L'ingénieur principal de JBoss sur ce sujet (Anil Saldhana) a même déclaré qu'il refuse d'activer JASPIC par défaut pour le moment. Quelques-unes des bugs les plus graves Jboss AS 7.1 ont été récemment fixes , mais comme il n'y a pas de communiqués publics de JBoss 7.1.x prévue plus et JBoss AS 7.2 est encore un peu de temps loin, cela signifie que maintenant au moins sur JBoss JASPIC est gênant.

Une autre question est regrettable que le module d'authentification réelle peut être normalisée, mais il n'y a aucun moyen déclarative (lire le fichier XML) pour le configurer qui est standardisé.

  

est-il de toute façon possible de déployer ce royaume d'un .war, ou le fait   toujours besoin d'être chargé à partir du propre chemin de classe serveur?

Avec JASPIC, le module d'authentification ( 'realm') peut en effet être chargé d'un .war. Je ne suis pas 100% sûr que cela est garanti par les spécifications, mais des 4 serveurs que j'ai testé (GlassFish, WebLogic, Geronimo et JBoss AS), ils ont tous soutenu cela. Geronimo a malheureusement une sorte de condition de course dans son enregistrement programmatique, vous avez donc besoin d'une solution de contournement laid en faisant un double déploiement à chaud, mais à la fin si ne charge le module du .war.

Comme les mécanismes de propriété, d'au moins JBoss AS a toujours soutenu le chargement du module (par exemple, une sous-classe de org.jboss.security.auth.spi.AbstractServerLoginModule) à partir du .war ou .ear.

Je a écrit un billet de blog sur ce sujet récemment qui a un peu plus détails.

Vous ne pouvez jamais déployer un royaume d'une guerre parce que le royaume est pas un artefact d'application, il est un artefact conteneur (donc l'expression « sécurité à base de conteneur »). Vous pouvez configurer votre application pour utiliser un domaine spécifique tel que prévu par le conteneur, mais l'application ne peut pas pourvoit elle-même.

Cela dit, alors que tous les conteneurs sont différents, et ces domaines ne sont pas portables, simple sens commun permettra de réduire les différences au peu de code de colle nécessaire pour intégrer le récipient, si vous êtes à la recherche pour la portabilité.

Avoir a un rapide coup d'oeil à la documentation Suns il semble que vous devrez écrire un LoginModule personnalisé qui étend leur serveur d'applications classe spécifique. Cela semble un peu en arrière pour moi et une limitation de Glassfish.

Si vous voulez rendre plus portable, je vous suggère de mettre l'essentiel de la mise en œuvre dans un LoginModule personnalisé développé contre l'interface standard de JavaEE (s) et ayant une fine couche de mise en œuvre spécifique à Glassfish que les délégués à la norme , la mise en œuvre portable.

Consultez article de Sun sur ce sujet .

Je ne fait réellement moi-même, mais je suis assez confiant chaque AS vous donne une option pour enregistrer de nouveaux domaines (domaines de sécurité) sur elle.

Il ne sera probablement pas 100% portable, et pour chaque AS vous pourriez avoir besoin d'un XML de configuration différente, mais au fond, il n'y a aucune raison pour que le code soit différent.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top