Pregunta

Estoy escribiendo una aplicación Java Web que necesitan para llevar a cabo de inicio de sesión a través de un servicio web. Por supuesto, ninguno de los reinos que se suministran con el servidor de aplicaciones que estoy usando (GlassFish v2) puede hacer el truco. Por lo tanto, tenía que escribir mi propia. Parece sin embargo, que la aplicación reino que escribí está completamente ligada a glassfish y no puede ser utilizado tal cual en cualquier otro servidor de aplicaciones.

¿Hay alguna manera estándar o un amplio apoyo para implementar un reino personalizada? Es en cualquier manera posible para desplegar ese reino de un .war, o que siempre necesita ser cargado de la propia ruta de clase del servidor?

¿Fue útil?

Solución

NOTA: La respuesta a continuación sólo es válida para Java EE 5. Como se ha llamado la atención en una de las otras respuestas, Java EE 6 soporta esto. Así que si estás usando Java EE 6, no lea esta respuesta, pero leer la otra respuesta correspondiente.

A partir de mi propia investigación y de las respuestas a esta pregunta la respuesta que he encontrado es la siguiente: A pesar de JAAS es una interfaz estándar, no hay manera uniforme a escribir, implementar e integrar una Realm JAAS + LoginModule en varios servidores de aplicaciones.

GlassFish V2 se requiere extender algunas de sus propias clases internas que implementan LoginModule o ellos mismos Reino. No obstante, usted no se puede personalizar todo el proceso de inicio de sesión debido a que muchos métodos de la interfaz LoginModule están marcados final en la superclase de Glassfish. Las clases LoginModule y Realm personalizados deben ser colocados en la ruta de clase AS (no el de la aplicación), y el reino deben estar registrados manualmente (sin el despliegue de la posible .war).

La situación parece ser un poco mejor para Tomcat, que le permitirá codificar su propio reino y LoginModule por completo, y luego configurarlos en el servidor de aplicaciones utilizando su propio JAASRealm (que delegar el trabajo real a sus implementaciones de Realm y LoginModule). Sin embargo, incluso Tomcat no permite el despliegue de su ámbito personalizados desde su .war.

Tenga en cuenta que ninguno de los servidores de aplicaciones que se presentaron los resultados de mi parece ser capaz de sacar el máximo provecho de toda la JAAS devoluciones de llamada. Todos ellos parecen apoyar sólo el esquema básico nombre de usuario + contraseña. Si necesitas algo más complicado que eso, entonces usted tendrá que encontrar una solución que no sea gestionada por el contenedor Java EE.

A modo de referencia, y porque se pidió en los comentarios a mi pregunta, aquí está el código que escribí para glassfishv2.

En primer lugar, aquí está la aplicación 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;
}
}

Y a continuación, la aplicación 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;
}
}

Por último, en el Reino tiene que estar atado a la LoginModule. Esto se hace a nivel de archivo de configuración de JAAS, que en la versión 2 se encuentra en glassfish suDominio / config / login.conf. Añadir las siguientes líneas al final de ese archivo:

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

Esto es lo que puso las cosas que trabajan para mí en GlassFish. Una vez más, esta solución no es portable a través de los servidores de aplicaciones, pero por lo que puedo decir, no hay una solución portátil existente.

Otros consejos

  

¿Hay alguna manera estándar o un amplio apoyo para implementar una costumbre   ¿Reino? Es en cualquier manera posible para desplegar ese reino de un .war, o   siempre necesita que se cargue de la propia ruta de clase del servidor?

No hay absolutamente una forma estándar para implementar un reino de encargo, o en términos más generales un módulo de autenticación personalizado. Esto se puede hacer a través de la JASPIC / Jaspi / JSR 196 SPI / API . JASPIC es una parte estándar de cualquier aplicación plena de Java EE 6, pero por desgracia no es parte del perfil de Java EE 6 Web.

Sin embargo, a pesar de ser un JASPIC parte de Java EE 6, que no está siendo apoyado de manera óptima por los vendedores. GlassFish y WebLogic parecen tener muy buenas implementaciones, JBoss AS y Gerónimo son un poco más problemático. El ingeniero jefe de JBoss sobre este tema (Anil Saldhana) incluso ha declarado que se niega a activar JASPIC por defecto por el momento. Algunos de los errores más graves en JBoss AS 7.1 han sido recientemente fijas, pero como no hay comunicados públicos de JBoss 7.1.x programada más y JBoss AS 7.2 es todavía algún tiempo lejos que significa a partir de ahora, al menos en JBoss JASPIC es problemático.

Otra cuestión es lamentable que el módulo de autenticación real puede ser estandarizada, pero no hay manera declarativa (leer el archivo XML) para configurarlo que está estandarizada.

  

Es en todo lo posible para desplegar ese reino de un .war, o lo hace   Siempre que tenga que ser cargado de la propia ruta de clase del servidor?

Con JASPIC, el módulo de autenticación ( 'reino') puede de hecho ser cargados desde un .war. No estoy 100% seguro de si esto está garantizado por la especificación, sino de los 4 servidores que probé (GlassFish, WebLogic, Gerónimo y JBoss AS), todos apoyaron esto. Gerónimo, desafortunadamente, tiene algún tipo de condición de carrera en su registro de programación, por lo que necesita una solución fea haciendo un despliegue en caliente dos veces, pero al final si no se carga el módulo de la .war.

A partir de los mecanismos de propiedad, al menos JBoss AS ha siempre apoyado cargar el módulo (por ejemplo, una subclase de org.jboss.security.auth.spi.AbstractServerLoginModule) de la .war o .ear.

escribió una entrada de blog sobre este tema recientemente que tiene un poco más de detalles.

Nunca se puede implementar un reino de una guerra porque el reino no es un artefacto de aplicación, es un contenedor de artefactos (por lo tanto la "seguridad basada contenedor" frase). Usted puede configurar su aplicación para utilizar un dominio específico según lo dispuesto por el contenedor, pero la aplicación no puede proporcionar esta misma.

Dicho esto, mientras que todos los recipientes son diferentes, y estos reinos no son portables, simple sentido común a reducir las diferencias con el poco de código de unión necesaria para integrarse con el contenedor, si usted está buscando para la portabilidad.

Tener tiene un rápido vistazo a la documentación Soles parece que tendrá que escribir una LoginModule a medida que se extiende la clase específica del servidor de aplicaciones. Esto parece un poco hacia atrás para mí y una limitación de Glassfish.

Si quieres que esto sea más portátil, sugeriría poner el grueso de la aplicación en un LoginModule personalizada desarrollada en contra de la interfaz de JavaEE norma (s) y luego tener una capa delgada aplicación específica a Glassfish que los delegados a la norma , aplicación portátil.

Salida artículo de Sun sobre este tema .

En realidad nunca hice esto por mí mismo, pero estoy bastante seguro de cada AS le da una opción para registrar nuevos dominios (dominios de seguridad) en él.

Es probable que no sea 100% portátil, y para cada uno como se podría necesitar un XML de configuración diferente, pero básicamente, no hay ninguna razón para que el código sea diferente.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top