Download Seguridad Empresarial en Java - unsj
Document related concepts
no text concepts found
Transcript
7tWXOR6HJXULGDGHPSUHVDULDOHQ-DYD $XWRUHV Ortega, Manuel Oscar - [email protected] Frias, Natalia - [email protected] Rodríguez, Nelson - [email protected] Docentes e investigadores del Departamento de Informática, de la Facultad de Ciencias Exactas, Físicas y Naturales de la Universidad Nacional de San Juan. 3UR\HFWRGH,QYHVWLJDFLyQ Entorno para la construcción de evaluacióon en Red. ,QWURGXFFLyQ Los sistemas empresariales frecuentemente son entornos de computación distribuida a gran escala que implementan una funcionalidad vital para el funcionamiento de una empresa u organización. Asegurar el sistema empresarial distribuido es, por tanto, una preocupación fundamental para las empresas y organizaciones que deseen mantener seguridad en sus operaciones clave. Las tecnologías de sistemas empresariales Java de la plataforma Java 2 Edición Empresarial (J2EE), se emplean hoy en día en los sistemas empresariales para proteger las operaciones clave (los datos, las comunicaciones, la Web y las aplicaciones) de una empresa. Un conjunto de mecanismos de seguridad empresarial estándar que complementan estas tecnologías también se proporciona tanto en los entornos empresariales Java como en los entornos J2EE. Este trabajo ofrece una introducción a: • Las tecnologías de sistemas empresariales Java más importantes. • La provisión de la seguridad en la conectividad empresarial de base de datos Java. • La provisión de seguridad en los en los paradigmas de comunicación empresarial de Java. • La provisión de la seguridad sobre servicios de comunicación empresarial Java. • La provisión de seguridad de los componentes EJB y Web basados en contenedores Java. 7HFQRORJtDGHVLVWHPDVHPSUHVDULDOHVGLVWULEXLGRV Los sistemas empresariales abarcan algunos sistemas distribuidos, escalables, multiusuario que están íntimamente relacionados con la mejora de la productividad de una empresa u organización a través de la tecnología de la información. Cada vez más, las empresas y organizaciones se están comprometiendo en una red informativa compleja en un esfuerzo por mejorar la productividad de sus operaciones por motivos de competitividad y de reducción de costos. El comercio electrónico, Internet/Web, la conectividad de negocio a negocio (B2B), la integración de aplicaciones empresariales (EAI), y la extracción de datos son sólo unos cuantos requisitos que deben ser satisfechos por diseños de sistemas empresariales. Las tecnologías empresariales Java y la plataforma Java 2 Edición Empresarial (J2EE), en particular, ofrecen una solución a la construcción más efectiva y rápida de sistemas empresariales que puedan generar software empresarial reutilizable, escalable, distribuible, mantenible, seguro, fiable y disponible. En esta sección analizaremos brevemente las tecnologías de sistemas empresariales Java, de forma que pueda comprender mejor los mecanismos de seguridad específicos que proporcionan estas tecnologías. En este trabajo, dividiremos el problema de los sistemas empresariales distribuidos en cuatro categorías principales: • Conectividad empresarial de base de datos: proporciona una forma de acceder a los datos almacenados en una base de datos. 1 • • • Comunicaciones empresariales: proporciona una forma de comunicarse entre procesos distribuidos por una red. Servicios empresariales de comunicación: proporcionan servicios comunes construidos sobre un paradigma de comunicaciones distribuidas empleadas por aplicaciones empresariales, independientemente del dominio de aplicación de que se trate. Componentes empresariales basados en contenedores: proporcionan paradigmas de programación del lado del servidor que permiten a los desarrolladores centrarse en tareas de desarrollo de componentes específicas de la aplicación, al tiempo que utilizan una infraestructura de contenedor/servidor para administrar el ciclo de vida y la configuración de tales componentes. &RQHFWLYLGDGHPSUHVDULDOGHEDVHGHGDWRV El acceso a almacenes de datos empresariales es extremadamente importante para la construcción de sistemas empresariales. Existe una gran variedad de formas para conectar aplicaciones empresariales Java con datos empresariales almacenados en bases de datos, pero la API Java DataBase Connectivity, (JDBC), es la estructura de datos empresariales más común y rica en prestaciones de Java. JDBC constituye una parte de J2EE y ha sido utilizada con mucha frecuencia por las organizaciones en su versión JDBC 1.x que se incluye en el JDK v1.1. JDBC 2.0 ofrece nueva funcionalidad al núcleo del J2EE y unas cuantas extensiones importantes específicas de la empresa en el J2EE. El desarrollo básico de JDBC implica el uso de la API JDBC con un controlador JDBC asociado que manipula la conexión de la base de datos concreta que le interese. La API JDBC se emplea para solicitar un puntero a una conexión de base de datos a partir del controlador JDBC. La conexión JDBC puede utilizarse entonces para crear instrucciones SQL, instrucciones preparadas o llamadas a procedimientos almacenados. Cuando se consultan datos, se devuelve un conjunto de resultados JDBC que se puede usar para obtener datos de las bases de datos. Las opciones avanzadas de JDBC 2.0 le permiten examinar esos conjuntos de resultados de un modo más flexible, llevar a cabo actualizaciones directamente desde el conjunto de resultados, y realizar actualizaciones por lotes en la base de datos. Además, ahora se puede manipular una amplia gama de tipos de SQL avanzados con JDBC 2.0. Por último, la especificación JDBC 2.0 define estándares para fabricantes de PLGGOHZDUH para el volcado de conexión de base de datos y la administración de recursos de transacciones distribuidas. &RPXQLFDFLRQHVHPSUHVDULDOHV La transferencia y la recepción de información empresarial en computadoras de la empresa es una consideración a tener en cuenta en cualquier tarea de desarrollo de sistemas empresariales. Proporcionar una solución de computación empresarial normalmente implica ofrecer una solución en la que pueda interoperar y comunicar una gama heterogénea y, a menudo, dispersa de plataformas y dispositivos de computación por las distintas redes de comunicación que conectan la empresa. Además, a medida que se van añadiendo plataformas y dispositivos de computación a la empresa, las comunicaciones empresariales, así como los sistemas de software de aplicaciones, deberán aumentar para satisfacer la demanda creciente en la red. El soporte estándar basado en Java se da en tres paradigmas clave de comunicación empresarial distribuida: • Redes TCP/IP básicas: las comunicaciones de red de los sistemas empresariales son TCP/IP, representa el protocolo de comunicaciones fundamental que utilizan la mayoría de los paradigmas de comunicaciones empresariales Java. La programación de sockets ofrece una API a las pilas de protocolos TCP/IP. La plataforma Java incorpora en el paquete java.net una serie de API´s estándar de programación de sockets basadas en Java. Una clase Socket encapsula un marcador básico de un socket TCP/IP , mientras que se utiliza una clase ServerSocket para crear sockets de servidor TCP/IP. Las bibliotecas de sockets Java 2 • • pueden ser personalizadas para implementar protocolos modularmente por TCP/IP utilizando clases e interfaces, como SocketImplFactory. RMI: la plataforma Remote Method Invocation, es un modelo de comunicaciones de objetos distribuidos centrados en Java. Al usar los paquetes e infraestructura RMI, los clientes Java basados en RMI pueden invocar remotamente métodos sobre los objetos del servidor Java basados en RMI. RMI permite a los clientes y servidores pasar objetos como parámetros de método y devolver valores por valor o referencia. Si una clase utilizada como parámetro de método o de retorno es desconocida para el cliente o el servidor, podrá ser cargado dinámicamente utilizando especificaciones RMI. Aunque los objetos servidor pueden construirse y enlazarse explícitamente en el lado del servidor en un servicio de búsqueda, los objetos servidor también se podrán activar automáticamente a petición del cliente sin instancia previa alguna del objeto del lado del servidor. RMI puede operar con TCP/IP a través de un protocolo específico de Java llamado Java Remote Method Protocol (JRMP), o a través de un protocolo de estándares abiertos, conocido como Internet Inter-ORB Protocol (IIOP). CORBA: la Common Object Request Broker Architecture, es un cuerpo de especificaciones neutral al lenguaje y a la plataforma que sirve para construir aplicaciones de objetos distribuidos creados por el consorcio de empresas Object Management Group. Las aplicaciones CORBA se construyen para ser ampliamente aisladas de los detalles del código del código de comunicaciones. Los objetos Common Object Services Specification (CORBAservices), Common Facilities Architecture (CORBAfacilities), y los objetos de negocios CORBA son todos ellos estándares construidos sobre CORBA que proporcionan un paquete muy rico de servicios y estructuras de comunicación distribuida. El CORBA Interface Definition Language (IDL), ofrece un mecanismo neutral al lenguaje que sirve para definir interfaces de objetos distribuidos con estándares que existen para asignar IDL a Java, así como para asignar Java a IDL. Por último, los objetos CORBA tienen la posibilidad de pasarse por referencia o valor. El estándar abierto principal, que es el protocolo basado en TCP/IP para la comunicación a través de CORBA, es el General InterORB (GIOP), que funciona sobre el Protocolo Inter-ORB de Internet (IIOP). 6HUYLFLRVGHFRPXQLFDFLyQHPSUHVDULDO Aparte de los paradigmas de comunicación distribuida subyacentes, muchos servicios están construidos sobre estos modelos de comunicación para hacer que las comunicaciones distribuidas de empresa sean más útiles a las aplicaciones empresariales. Los servicios de nombres proporcionan una forma de asignación entre referencias a objetos distribuidos y nombres de objetos legibles. Los sistemas empresariales también emplean a menudo servicios de directorio y comerciales para localizar y descubrir objetos distribuidos en una red que utiliza atributos descriptivos e información de tipos acerca de esos objetos. Los mensajes asíncronos que se envían entre productores y consumidores a menudo se engloban en una de las muchas opciones de servicios de mensajería que están disponibles para el desarrollador de sistemas empresariales Java. Tales servicios son comunes a muchas aplicaciones empresariales distribuidas basadas en comunicaciones y también son componentes fundamentales de una solución empresarial Java integrada. Existe un soporte estándar basado en Java para cuatro API’s de servicios empresariales de comunicación clave: • Java Naming and Directory Interface (JNDI): un servicio de nombres es el mecanismo principal que se utiliza en los sistemas distribuidos para hacer referencia a objetos desde las aplicaciones a través de un nombre que identifica a ese objeto. Los servicios de directorio ofrecen una forma de buscar objetos en distintos contextos de nombres dada una serie de atributos de objeto. JNDI ofrece un medio principal para engancharse a los sistemas de nombres y directorio a partir de aplicaciones empresariales Java. JNDI define una API estándar para interactuar con tales servicios, y permite que distintos tipos y proveedores se conecten a la estructura a través de una interfaz de proveedor de servicios. 3 • • • Jini: los servicios comerciales proporcionan una estructura para que los objetos se identifiquen a sí mismos en un sistema distribuido, utilidades para buscar y descubrir otros servicios y servicios de objetos remotos. La tecnología Jini es, es esencia, un servicio comercial en el que se registra, con un servicio de búsqueda, información descriptiva acerca de procesos o dispositivos remotos. Los clientes Jini pueden buscar tales servicios utilizando una descripción de plantilla y obtener una serie de elementos de servicio de esas búsquedas. Los objetos proxy devueltos por estas búsquedas pueden representar marcadores de procesos o dispositivos remotos. Jini también añade un mecanismo para que los servicios y los clientes Jini descubran dinámicamente servicios de búsqueda Jini utilizados para el comercio. Java Message Service (JMS): es una API Java que define el modo en que las aplicaciones pueden interactuar con los proveedores de servicios asíncronos de mensajería de un modo estándar. JMS también incluye una interfaz que es implementada por los proveedores de servicios de mensajería subyacentes para ofrecer servicios JMS a los clientes. JMS ofrece un modelo de publicación-suscripción de mensajería punto a punto. La mensajería punto a punto se lleva a cabo con la implementación de una jerarquía de nodos tópicos en los que los productores publican mensajes y a los que los consumidores se pueden suscribir. JMS proporciona una arquitectura de mensajería abstracta que es ampliada por el modelo de cola de punto a punto y el modelo de publicación-suscripción. JavaMail: los sistemas de mensajería de correo electrónico juegan en la empresa un papel muy importante y específico de la aplicación. JavaMail ofrece una forma de interactuar con un sistema de mensajería de correo electrónico. Con JavaMail, las aplicaciones empresariales pueden enviar y recibir mensajes de correo a través de Internet. Por tanto, JavaMail proporciona una API para hacer de interfaz con almacenes de mensajes remotos utilizados para recibir mensajes de correo y para interactuar con transportes de mensajes remotos utilizados para enviar mensajes de correo electrónico. &RPSRQHQWHVHPSUHVDULDOHVEDVDGRVHQFRQWHQHGRUHV El modelo de componente/contenedor J2EE de desarrollo de aplicaciones empresariales modernas implica el uso de un entorno de contenedor de terceras partes en el que puedan operar los componentes empresariales. Los contenedores ofrecen distintas API’s de servicios e implementaciones, así como entornos de aplicación autónomos. Sin embargo, los entornos de contenedor también ofrecen servicios de administración y configuración. Los servicios de administración ofrecen implementaciones de infraestructura para administrar el ciclo de vida, la manipulación de hilos, la manipulación de las comunicaciones, el volcado de recursos y la provisión de seguridad en los sistemas para los componentes que operen dentro de sus límites. Los contenedores J2EE también proporcionan una forma estándar para configurar el estado y los parámetros de servicio para los componentes que utilicen descriptores de despliegue estándar basados en XML. En la especificación J2EE se definen dos clases principales de componentes empresariales del lado del servidor y sus contenedores, los cuales describiremos aquí: • Componentes web: los componentes web se definen por medio de VHUYOHWV Java o páginas JavaServer (JSP). Los componentes web representan la manipulación específica de la aplicación de solicitudes recibidas por un servidor web y generan respuestas web. Desde el punto de vista de la administración de contenedores, los VHUYOHWV Java y las JSP reciben un tratamiento casi idéntico. De hecho, aunque los VHUYOHWV Java basados en web son componentes Java que utilizan peticiones web estándar y API de respuestas, las JSP se compilan en VHUYOHWV Java. Sin embargo, las JSP pueden definirse de una forma que es más familiar para los desarrolladores web. Por ejemplo, los datos de plantilla HTML pueden incrustarse directamente en la JSP. • Componentes empresariales JavaBeans (EJB): EJB proporciona un modelo para el desarrollo de componentes de aplicaciones empresariales del lado del servidor que pueden hacer que la tarea de creación de aplicaciones empresariales portables y distribuidas sean 4 más fácil que la construcción de aplicaciones empresariales autónomas. Los contenedores/servidores EJB proporcionan servicios distribuidos de comunicaciones, servicios de activación de datos, servicios distribuidos comunes de comunicaciones, servicios de activación de seguridad de sistemas para componentes EJB. Además, se requiere un mínimo esfuerzo por parte del desarrollador para utilizar estos servicios. Actualmente, se pueden desarrollar cuatro tipos de EJB. Los componentes (EHDQV) de sesión sin estado que sirven como motores sin estado de entrada/salida que reciben peticiones de clientes EJB y generan respuestas. Los componentes de sesión con estado mantienen el estado entre llamadas sucesivas sobre el componente a cargo del mismo cliente EJB. Los componentes de entidad de persistencia son componentes que encapsulan datos persistentes y que exigen que el código de acceso a datos lo haya escrito el desarrollador de componentes (probablemente con JDBC). Los componentes de entidad de persistencia administrados por contenedores son componentes que encapsulan datos persistentes y que activan el código de acceso a datos para que lo genere automáticamente el proveedor del contenedor. 6HJXULGDGHQODFRQHFWLYLGDGHPSUHVDULDOGHEDVHGHGDWRV Los datos que fluyen entre un cliente de base de datos y un servidor de base de datos tienen una naturaleza sensible. Estos datos pueden ser confidenciales y sólo pueden ser vistos por determinados usuarios. Además, una solución de seguridad con conectividad de base de datos también puede requerir un modo de limitar el acceso del usuario a determinados tipos de datos. En tales casos, se suele requerir una forma de que los clientes de las bases de datos se autentiquen a sí mismos con el servidor de base de datos. Dado que las aplicaciones empresariales Java se conectan a las bases de datos principalmente a través de JDBC, algunos medios para ofrecer conexiones JDBC seguras tienen que ser considerados. Cuando se usa JDBC en un entorno de aplicación empresarial autónoma (es decir J2EE), hay que proporcionar a través de JDBC un mecanismo para autenticarse a sí mismo y para establecer el acceso a los datos confidenciales. En entornos J2EE EJB basados en contenedor, los desarrolladores pueden considerar requerimientos similares de seguridad si están usando JDBC como mecanismo de acceso a bases de datos. Estos desarrolladores de componentes de entidad de persistencia administrados por contenedor deben considerar el modo en que el contenedor J2EE va a proporcionar tales servicios. 6HJXULGDGHPSUHVDULDOHQODVFRPXQLFDFLRQHV Debido a que el uso de paradigmas de comunicaciones es tan común en entornos empresariales distribuidos, hay que considerar una forma de asegurar este paradigma. Por desgracia, la forma más elemental de proporcionar seguridad empresarial de las comunicaciones para aplicaciones basadas en Java está limitada. La consideración principal a la hora de proporcionar seguridad empresarial en las comunicaciones ha sido de naturaleza sensible del código Java. Debido a ello, esta forma de limitar el acceso a recursos fiables por código descargado o para llevar a cabo operaciones de red básicas es casi exclusiva de la seguridad de red basada en TCP/IP y en RMI. Otras extensiones para la autenticación y la confidencialidad se utilizan a veces para aumentar la seguridad de estos modelos. Las aplicaciones CORBA basadas en Java pueden aprovechar el modelo de seguridad CORBA, que es más complejo. Esta sección explora las opciones elementales para asegurar estos paradigmas distribuidos de comunicaciones empresariales basados en Java. 6HJXULGDGEiVLFDHQODVUHGHV Proporcionar una seguridad básica en la red con Java gira en torno al uso del modelo de control de seguridad-acceso basado en permisos de Java 2. Los permisos de red tienen nombres que hacen referencia a un recurso de red en el que el permiso puede ser concedido o denegado. Los permisos de VRFNHW de red también tienen una serie de acciones que abarcan la serie de operaciones de VRFNHW que se pueden llevar a cabo. 5 Tres subclases MDYDVHFXULW\3HUPLVVLRQ nos sirven para definir la serie principal de permisos de seguridad de Java 2, que se pueden usar para proporcionar un control de acceso seguro para la seguridad de la red. Estas clases de permisos relacionadas con las redes son las clases MDYDQHW6RFNHW3HUPLVVLRQ, MDYDQHW1HW3HUPLVVLRQ y MDYDODQJ5XQWLPH. Aunque los permisos para acceder a recursos de red a partir de una JVM están encapsulados por los permisos de jerarquía de la API Java, la administración de tales permisos de un modo configurable la encapsula la infraestructura de normas de seguridad de Java 2. El control de acceso en Java 2 está administrado por las clases MDYDVHFXULW\$FFHVV&RQWUROOHU y MDYDVHFXULW\$FFHVV&RQWURO&RQWH[W La clase 6RFNHW3HUPLVVLRQ encapsula permisos de un VRFNHW de red. Un SocketPermission se construye con un nombre de KRVWy una serie de acciones, como se ilustra en la tabla 1.1. 7DEOD Tipos de permisos de un VRFNHW 1RPEUH\DFFLyQGHOSHUPLVRGHVRFNHW 'HVFULSFLyQ SocketPermission sp=new SocketPermission(“www.prueba.com”, “accept”); SocketPermission sp=new SocketPermission(“205.127.44.44”, “accept, connect”); SocketPermission sp=new SocketPermission(“*.com”, “accept, connect”); Da permiso para aceptar conexiones de un solo nombre de dominio. Da permiso para aceptar conexiones y conectarse con una determinada dirección IP Da permiso para aceptar/conectar en cualquier nombre de dominio que termine con .com. Da permiso para aceptar/conectar en el puerto 80 del dominio prueba.com. SocketPermission sp=new SocketPermission(“*.prueba.com:80”, “accept, connect”); SocketPermission sp=new SocketPermission(“*.prueba.com:1024-”, “accept, connect”); SocketPermission sp=new SocketPermission(“*.prueba.com:-1013”, “accept, connect”); SocketPermission sp=new SocketPermission(“www.prueba.com:4000:4020”, “accept, connect”); SocketPermission sp=new SocketPermission(“*”, “accept, connect”); SocketPermission sp=new SocketPermission(“”, “accept, listen, connect”); SocketPermission sp=new SocketPermission(“localhost”, “accept, connect”); Acepta/conecta en los puertos no reservados. Acepta/conecta reservados. en los puertos Acepta/conecta en los puertos 4000 a 4020. Acepta/conecta en todas las máquinas en todos los puertos. Acepta/conecta/escucha sólo en localhost. Acepta/conecta/escucha sólo en localhost. El nombre del KRVW de destino y las acciones que se especifican en un archivo de normas de seguridad Java 2 adopta la forma: grant { permission java.io.SocketPermission “localhost”, “accept, listen, connect”; permission java.net.SocketPermission www.prueba.com”, “accept”; }; Los permisos para redes que se definen a través de la clase NetPermission sólo tienen un nombre de destino sin acciones definidas. Un NetPermission se construye con uno de los nombres de destino, como se ilustra en la Tabla 1.2. 6 Tipos de permisos para redes 7DEOD 1RPEUHGHOSHUPLVRSDUDUHGHV 'HVFULSFLyQ NetPermission np=new NetPermission(“requestPasswordAuthentication”); Da permiso para obtener una constraseña de la java.net.PasswordAuthentication registrada. Da permiso para registrar el java.net.Authenticator utilizado para obtener información de autenticación. Da permiso para designar un manipulador de flujos al crear una URL. NetPermission np=new NetPermission(“setDefaultAuthenticator”); NetPermission np=new NetPermission(“specifyStreamHandler”); Como observará que el uso de las clases java.net.Authenticator y java.net.PasswordAuthentication se ve afectado por las dos primeras filas de la Tabla 1.2. La clase java.net.Authenticator proporciona formas de obtener información sobre la autenticación desde una conexión de red. Las subclases se registran con el proceso JVM a cargo de una aplicación Java a través de una llamada al método estático Authenticator.setDefault(Authenticator). Si se concede el permiso “setDefaultAuthenticator”, la llamada a este método será permitida; caso contrario, se presentará una SecurityException. El método getPasswordAuthentication() se invoca en la subclase Authenticator durante la autenticación basada en constraseña. Se puede utilizar un objeto PasswordAuthentication para devolver una cadena de nombre de usuario y una matriz char[] de constraseña. Se puede hacer una llamada estática Authenticator.requestPasswordAuthentication() se el proceso JVM establece el permiso “requestPasswordAuthentication”. El método requestPasswordAuthentication() pide un objeto PasswordAuthentication al autenticador que se ha registrado en el sistema. Se proporciona un objeto InetAddress que especifica la dirección de petición de usuario y una cadena de esquema de protocolo como entrada al método requestPasswordAuthentication(). Por último, aparte de los tipos SocketPermission y NetPermission, se puede usar un nombre de destino “setFactory” afiliado a RuntimePermission con el fin de permitir que una aplicación establezca una factoría de VRFNHWV distinta a través de las clases java.net.Socket y java.net.ServerSocket. La posibilidad de establecer un manipulador de flujos URL a través de la clase java.net.URL también se ve afectada por este permiso. Todos estos mecanismos de seguridad básicos en las redes Java solamente permiten la provisión de un control de acceso básico para operaciones fiables de redes. No se ofrecen explícitamente formas de autenticar clientes y servidores de red o de proveer sesiones confidenciales. Para tales servicios, es posible utilizar las API Java Authentication and Authorization Service (JAAS), y Java Secure Socket Extension (JSSE) que se empaquetan por separado. 6HJXULGDG50, Las formas predeterminadas de proporcionar seguridad a las aplicaciones basadas en RMI es java.rmi.RMISecurityManager. Se puede usar para definir parámetros de seguridad que dirigen la descarga de código en virtud de las características propias de RMI para la descarga de código dinámico. Cuando no se establece un administrador de seguridad en una aplicación basada en RMI, no se descargará código RMI desde ubicaciones remotas. Durante el inicio de una aplicación basada en RMI, normalmente se establece el uso de RMISecurityManager a través de una llamada, de esta forma: Java.lang.System.setSecurityManager(new java.rmi.RMISecurityManager()); 7 La forma estándar en virtud de la cual se establecen normas de seguridad Java 2 en ciertas ubicaciones de bases de código pueden utilizarse para controlar los niveles de permiso en aplicaciones basadas en RMI. Tales mecanismos sólo conceden o deniegan el acceso a determinados recursos JVM para código RMI descargado de una ubicación remota. Los temas amplios de proporcionar autenticación y confidencialidad en sesiones de cliente/servidor RMI no entran en el modelo actual de RMI. El JAAS se puede usar en conjunción con RMI y con el modelo de seguridad de Java 2 para limitar el acceso basado en un determinado tema, aparte de la ubicación de la base de código descargada. Las extensiones de VRFNHWV SSL también se pueden utilizar para ofrecer una forma de asegurar la sesión de comunicaciones por la que viaja el tráfico RMI. Existe una nueva especificación para mejorar las opciones de seguridad de RMI. Esta especificación destaca los medios (formas) para autenticar sujetos cliente y servidor implicados en invocaciones de métodos remotos, medios para delegar al sujeto cliente tal que se puedan ejecutar invocaciones al servidor remoto en nombre del sujeto, y medios para dotar a los datos de integridad y confidencialidad al invocar a los métodos remotos. Estas mejoras cuentan con un paquete nuevo java.rmi.constraint, que contiene clases que permiten a los clientes y servidores imponer restricciones de seguridad sobre las invocaciones de métodos remotos. Las restricciones para especificar la integridad y confidencialidad de los datos enviados a través de invocaciones de métodos remotos vienen encapsuladas por las clases de este paquete. Las restricciones a la autenticación y asociación de identidades de cliente y servidor con las llamadas de métodos remotos también vienen encapsuladas por las clases de este paquete. 6HJXULGDGHQ&25%$ Las aplicaciones basadas en CORBA también requieren una forma de asegurar el paradigma de objeto distribuido CORBA. El Servicio de Seguridad de CORBA es un componente OMG CORBAService que hace referencia a la seguridad de objetos distribuidos en aplicaciones basadas en CORBA. Este servicio se define para que funcione principalmente sobre la capa ORB, pero también define algunos cambios en dicha capa. Al usar componentes que implementan la Especificación del Servicio de Seguridad, las aplicaciones empresariales basadas en CORBA obtienen la ventaja de la protección de seguridad basada en estándares, entre las se incluyen la protección de identidad, la autenticidad, la no repudiación, la autorización, la auditoría, la integridad y la confidencialidad. 6HJXULGDGGHVHUYLFLRVHPSUHVDULDOHVGHFRPXQLFDFLRQHV Por encima de la seguridad básica en las comunicaciones distribuidas, estos servicios comunes que se construyen sobre tales paradigmas distribuidos también podrían requerir un cierto grado de seguridad aumentada. Dado que tales servicios se suelen manifestar como servidores distribuidos, los primeros mecanismos necesarios para una utilización segura son: que los clientes se autentiquen a sí mismos con estos servidores. La confidencialidad de las sesiones con tales servicios suele proporcionarla el proveedor de servicios a nivel de la capa de transporte. En esta sección, exploraremos brevemente estos servicios de seguridad que se exponen a través de mecanismos Java estándar en servicios de comunicaciones distribuidas, como los servicios de nombres, de directorios, de comercio y de mensajería. Por lo tanto, exploraremos brevemente los mecanismos de seguridad estándar que proporcionan JNDI, Jini, JMS y JavaMail. 6HJXULGDGHQ-1', Para poder utilizar los servicios de un servicio de nombres o directorios, los usuarios de la API cliente JNDI crean primero una referencia a un contexto inicial del servicio de nombres o directorios que interese. Este proceso inicial de contexto/creación establece una conexión con el servicio cuando se construye con una serie de propiedades que describen qué biblioteca específica de proveedor de servicio de nombres o directorios usar, la URL del proceso de servicio de nombres o directorios, y quizá un nombre de usuario y unas credenciales de usuario. 8 También se pueden establecer otras propiedades, cuyos nombres se definen como atributos públicos estáticos en la interfaz javax.naming.Context. Una clase javax.naming.InitialContext que implementa la interfaz Context se puede usar para crear un puntero a un servicio de nombres concreto. Al pasar un objeto Properties establecido como elementos que utilizan los nombres de claves java.naming.XXX que se definen en la interfaz Context al constructor de InitialContext, se establecerán todas las propiedades públicas estáticas Context.XXX que sean necesarias, que se usarán durante la inicialización de InitialContext. En la tabla 1.3 se definen unas cuantas propiedades públicas estáticas relacionandas con la seguridad. 7DEOD Propiedades de contexto 3URSLHGDGGHFRQWH[WR 'HVFULSFLyQ INITIAL_CONTEXT_FACTORY Paquete completamente cualificado y nombre de clase del proveedor utilizada para crear un contexto JNDI. PROVIDER_URL URL que especifica el protocolo, host y puerto sobre el que se está ejecutando el servicio de nombres o directorios. Es decir: <protocolo>://<host>:<puerto>. SECURITY_PRINCIPAL Nombre del principal (por ejemplo, nombre de usuario) que tiene que ser comprobado por el servicio de nombres o directorios en caso de que se requiera autenticación. SECURITY_CREDENTIALS Credenciales del principal (por ejemplo, una contraseña) que tiene que ser comprobada por el servicio de nombres o directorios en caso de que requiera autenticación. SECURITY_PROTOCOL Especifica el protocolo de seguridad a utilizar (por ejemplo, SSL). SECURITY_AUTHENTICATION Especifica el nivel de seguridad que se va a usar, como none, simple o strong. AUTHORITATIVE El valor true indica que el acceso al servicio es para la fuente más autorizada. De todas las propiedades que se definen en la Tabla 1.3, las dos primeras (INITIAL_CONTEXT_FACTORY y PROVIDER_URL) probablemente sean las más utilizadas en los programas JNDI. Las propiedades SECURITY_PRINCIPAL y SECURITY_CREDENTIALS suelen emplearse con mucha frecuencia para la autenticación básica. Si una propiedad queda sin definirse, se suele utilizar un valor predeterminado, lo que es válido en la mayoría de los casos. La creación de un InitialContext es, por tanto, directa como se ve en este ejemplo: Properties propiedades=new Properties(); propiedades.setProperty(Context.INITIAL_CONTEXT_FACTORY,”com.unsj.MiJNDIFactory ”); propiedades.setProperty(Context.PROVIDER_URL,”protocol://123.205.155:5000”); propiedades.setProperty(Context.SECURITY_PRINCIPAL,”administrador”); propiedades.setProperty(Context.SECURITY_CREDENCIALS,”yamiout”); propiedades.setProperty(Context.SECURITY_PROTOCOL,”SSL”); propiedades.setProperty(Context.SECURITY_AUTHENTICATION,”strong”); Context contexto=new InitialContext(propiedades); Object miObjetoDistribuido=context.lookup(“NombreDeMiObjeto”); 6HJXULGDGHQ-LQL El entorno dinámico para redes de Jini puede suponer que haya una cantidad importante de código móvil que se intercambie entre procesos distribuidos. Por consiguiente, el acceso a los recursos y permisos de este código descargado deberá se controlado de algún modo. Desafortunadamente, el alcance de las consideraciones de seguridad que utiliza el modelo dinámico para redes de Jini está muy limitado. La seguridad en Jini se deriva del modelo de 9 seguridad básico de Java 2 y del uso de un administrador de seguridad RMI. De hecho, durante el proceso de descubriemiento Jini, el conjunto de grupos que pueden ser unidos por un servicio Jini o un cliente Jini puede limitarse a través de mecanismos de seguridad de Java 2. La clase net.jini.discovery.DiscoveryPermission encapsula un tipo de permiso Java 2 que limita el acceso a los recursos de determinados grupos de redes Jini. Cuando un cliente Jini, servicio Jini o servicio de búsqueda Jini trata de descubrir otros servicios de búsqueda en la red, invoca al constructor net.jini.discovery.LookupDiscovery con una lista de nombres de grupo del tipo String. Estas redes Jini que pertenecen a uno de los grupos especificados pueden ser descubiertas a través de este proceso. Si el usuario LookupDiscovery (cliente Jini, servicio Jini o servicio de búsqueda Jini) no tiene permiso para acceder a un determinado grupo, el proceso de descubrimiento de servicios de búsqueda Jini de ese grupo terminará por provocar una excepción de seguridad. La clase DiscoveryPermission y la representación asociada de su archivo de normas puede estar relacionada con un nombre de grupo de descubrimiento de destino. Este nombre de grupo puede ser definido en función de las formas siguientes: • “name”: un nombre de destino especificado identifica un determinado grupo de red Jini. • “public” o “”: la cadena “public” o una cadena vacía se pueden usar para designar un grupo público al que todas las aplicaciones pueden acceder. • “*”: identifica a todos los grupos. • “*.unj.edu.ar”: se puede usar un prefijo “*” para crear comodines de grupos en un determinado dominio de grupos. Por lo tanto, se puede especificar un DiscoveryPermission en un archivo de normas Java 2 estándar, como se ejemplifica aquí: grant SignedBy “UNSJ” CodBase “http://www.unsj.edu.ar/-“ { permission net.jini.discovery.DiscoveryPermission “alumnos”; }; En el ejemplo anterior, el código cargado por la aplicación Jini afectado por este archivo de normas concede permisos de descubrimiento a un grupo de destino denominado “alumnos” al código cargado en “http://www.unsj.edu.ar” y firmado por “UNSJ”. Por lo tanto, los procesos JVM de cliente Jini, de servicio Jini o de servicio de búsqueda Jini deberán estar asociados a unas normas de seguridad Java 2 durante el inicio. Además, las aplicaciones Jini deberán establecer un administrador de seguridad durante la inicialización utilizando un administrador de seguridad RMI, como RMISecurityManager que describimos anteriormente. Aunque tales controles indican qué grupos de búsqueda pueden ser descubiertos por sus aplicaciones, podría preguntarse: ¿cómo la infraestructura Jini puede autenticar tales grupos? Es decir, si configura su aplicación para que permita el descrubimiento de servicios de búsqueda pertenecientes al grupo “xyz”, ¿qué mecanismos garantizan que el servicio de búsqueda pertenece verdaderamente a un grupo? La respuesta más sencilla es que actualmente no se ofrecen las suficientes garantías. La firma de código y la especificación de la ubicación de la base de código son las únicas opciones reales que proporcionan algún nivel de garantía en la identidad del código. Anticipamos que Jini será ampliado en el futuro con mecanismos de seguridad más rigurosos. En concreto, el modelo de seguridad Jini, se capitalizará en el nuevo modelo de seguridad RMI que se está desarrollando. 10 6HJXULGDG-06 La seguridad en los sistemas de mensajería dependerá mucho del fabricante de PLGGOHZDUH. No obstante, JMS proporciona varias formas para permitir la autenticación sencilla de cliente basada en contraseña con el servidor de mensajes PLGGOHZDUH. JMS lleva a cabo esto permitiendo a los clientes JMS que faciliten al servidor de mensajes un nombre de usuario y una contraseña cuando se crea la conexión inicial con el servidor. Se puede usar un clase javax.jmsQueueConnectionFactory para crear un objeto inicial javax.jms.QueueConnection. QueueConnection representa la conexión de cliente con el servidor de cola de mensajes punto a punto de PLGGOHZDUH JMS. El método estático QueueConnectionFactory.createQueueConnection() puede tomar parámetros tipo String con el nombre del usuario y la contraseña que se utilizan para autenticar al cliente JMS frente al servidor middleware. Si la autenticación del cliente falla, se presentará una javax.jms.JMSSecurityException. El proceso es parecido en la mensajería de publicación-suscripción. Se puede usar una clase javax.jms.TopicConnectionFactory para crear un objeto inicial javax.jms.TopicConnection que representa la conexión de cliente con el servidor de temas de mensajes de publicaciónsuscripción de PLGGOHZDUH JMS. El método estático TopicConnectionFactory.createTopicConnection() puede entonces tomar las cadenas con el nombre de usuario y la contraseña como parámetros con el fin de autenticar el cliente JMS con el servidor de PLGGOHZDUH. Si falla la autenticación del cliente, se presenta una javax.jms.JMSSecurityException. 6HJXULGDGHQ-DYD0DLO La API JavaMail también expone una forma de permitir a los clientes autenticarse con un servidor de mensajería remoto. En este caso, el servidor de mensajería es un servidor de correo electrónico. Antes de que un cliente JavaMail pueda interactuar con un sistema de mensajería de correo electrónico, deberá establecer una sesión de correo con un servidor de correo. Se pueden usar dos métodos en la clase Session para obtener una instancia Session. El método getDefaultInstance() se utiliza para devolver una instancia de una sesión de correo que puede ser compartida por otras aplicaciones que se ejecuten en la misma plataforma. El método getInstance() se puede usar para crear una sesión de correo que sea única y que no esté compartida con otras aplicaciones. Ambos métodos toman un objeto javax.util.Properties como argumento que puede tener valores establecidos con elementos estándar de propiedad. La creación de un objeto Session también implica el uso de un parámetro javax.mail.Authenticator con tales métodos estáticos. La clase abstracta Authenticator está subclasificada por proveedores de servicios que implementan objetos que saben cómo autenticar un usuario con un servidor de correo. Si se emplea un Authenticator nulo para crear un objeto Session utilizando un método estático Session.getDefaultInstance() y la instancia predeterminada ya ha sido creada, el objeto Authenticator deberá coincidir con la instancia que se utilizó para crear la sesión original. El Authenticator lo usa principalmente el entorno de servicios de mensajería de correo como retrollamada para requerir información de autenticación del usuario. La clase javax.mail.PasswordAuthentication se usa para encapsular un nombre de usuario y una contraseña, que puede establecerse en el objeto Session utilizando setPasswordAuthentication(URLName, PasswordAuthentication) para su uso posterior en la sesión o a cargo de otras aplicaciones. El URLName encapsula los elementos de datos de un URL que, en este caso, se usa para asociar un URL de servidor de correo con la información de autenticación de la contraseña. Sin embargo, el Authenticator, la clase PasswordAuthentication 11 y los métodos asociados del objeto Session son utilizados por un proveedor de almacenamiento de mensajes o de transporte de correo. La forma principal en virtud de la cual el cliente de la aplicación JavaMail proporciona información sobre autenticación al sistema de correo se produce a través de un objeto javax.mail.Store o javax.mail.Transport. Tales objetos se obtienen del objeto Session. El objeto Store encapsula un puntero a un almacén de mensajes de correo electrónico (servidor POP o servidor IMAP) para recuperar mensajes de correo electrónico. El objeto Transport encapsula un marcador a un mecanismo de transporte de correo electrónico (servidor SMTP) que sirve para enviar mensajes de correo electrónico. Las clases Store y Transport se heredan ambas de la clase javax.mail.Service. La clase Service define una colección de métodos connect() que permiten al usuario JavaMail conectarse con el servicio de correo electrónico concreto (almacén de mensajes de correo de usuario o servicio de transporte). Dos de los métodos connect() aceptan un nombre de usuario y una contraseña para la autenticación de un usuario con el servidor de correo remoto. Utilizando tales métodos, un cliente de la API JavaMail puede autenticarse a sí mismo con un servidor SMTP, POP o IMAP al conectarse con tales servidores. 6HJXULGDGGHFRPSRQHQWHVHPSUHVDULDOHVEDVDGRVHQFRQWHQHGRUHV Los componentes basados en J2EE, como los servlets Java, JSP y EJB, emplean mecanismos de seguridad de alto nivel construidos sobre el modelo de seguridad básico de Java 2. Estos mecanismos liberan a la Web y al desarrollador de componentes EJB de la necesidad de saber mucho sobre el modelo de seguridad subyacente de Java 2. En vez de ello, los desarrolladores se centran en especificar las funciones de seguridad y las funciones asociadas con los privilegios de acceso a componentes. Esta sección describe las disposiciones básicas de seguridad de la seguridad de componentes web y EJB. 6HJXULGDGHQORVFRPSRQHQWHV:HE Las estructuras Java Servlet y JSP están integradas con muchas opciones de seguridad de Java 2.0 y también aumentan la estructura de seguridad de Java 2.0 con el fin de dar seguridad a los componentes web. La seguridad de Java Servlet y JSP (componente Web de Java) trata sobre la identidad y autenticación , la autorización, la integridad y la confidencialidad. En concreto, la estructura de componentes web J2EE ofrece un forma de definir declarativamente atributos de seguridad de un descriptor de despliegue XML de una aplicación web estándar que se usa para configurar los aspectos operativos de seguridad en línea de los componentes web. Alternativamente, ciertas prestaciones de la estructura de seguridad también se exponen a los componentes web a través de API que permiten la provisión de una seguridad programática más elaborada a cargo de desarrolladores de aplicaciones de componentes web. Un elemento de datos XML, que se define en el elemento raíz del descriptor de despliegue XML de una aplicación web estándar, se usa para definir la configuración de la autenticación concreta que utiliza una aplicación web. El tipo de autenticación que se puede usar puede especificarse de una de cuatro formas, entre las que se incluye la autenticación de contraseña básica, la autenticación basada en funciones resúmen de mensajes, la autenticación basada en formularios HTML y la autenticación basada en certificados de cliente SSL. Durante el tiempo de ejecución, cierta información relacionada con la autenticación y asociada con una petición HTTP también puede ser extraída en el lado del servidor por el servlet o JSP. Cuando una petición es enviada a un servidor web con un protocolo seguro, se puede usar un método del lado del servidor para devolver un valor booleano que indique este hecho. Cuando se utiliza SSL con HTTP, también se puede devolver una serie de objetos de certificado X509 desde una llamada al objeto requerido. Una vez que se ha identificado a un usuario con un mecanismo de autenticación concreto, puede determinarse la autorización para acceder a los recursos de componentes web identificados por 12 URL. La autorización de componentes web se basa en una técnica de control de acceso basada en funciones. Las funciones de seguridad se asignan a principales o grupos. Cuando un principal concreto realiza una petición sobre un recurso con una función de seguridad asociada, el nombre del principal o grupo que esté asociado con la función requerida, se pasa, con el fin de determinar si se permite o no el acceso al recurso. Se puede definir un conjunto de funciones de seguridad válidas para un entorno concreto de componentes web J2EE en el descriptor de despliegue XML de ese componente. 6HJXULGDGHQ(-% Actualmente, los mecanismos estándar de seguridad que se definen en los EJB se centran mucho en proporcionar un conjunto mínimo de construcciones para el control de acceso a la seguridad de EJB. Aunque un mecanismo para la autenticación de un usuario está implícito por el hecho de que a un determinado usuario se le debe conceder el acceso a un determinado método EJB, en EJB v1.1 y en J2EE v1.2 no se definen formas estándar de autenticar a un usuario. No obstante, tales mecanismos estándar están previstos para J2EE v1.3, y con toda probabilidad se centrarán en el uso del JAAS. Además, también se necesita una combinación de mecanismos de seguridad específicos del contenedor y definibles por el usuario para crear un entorno verdaderamente seguro y un entorno de seguridad práctico para los EJB. Aunque la especificación EJB no recomienda una lógica de control de acceso a la seguridad implementado por componentes, en muchos casos prácticos esto es inevitable. Siempre que se realice una llamada a un método de comprobación de funciones de seguridad EJB desde el código EJB, se deberán definir referencias de función asociadas en un descriptor de despliegue XML para el EJB. Tales referencias de función y otros mecanismos de especificación de funciones pueden ser utilizadas para definir declarativamente qué funciones de seguridad de los clientes EJB pueden invocar a métodos EJB concretos. 5HVXPHQ Cada vez más se utilizan tecnologías empresariales Java y J2EE en sistemas empresariales con el fin de permitir el acceso a los datos empresariales, a la conectividad de las comunicaciones a la Web y a la construcción de aplicaciones escalables de forma rápida. Java complementa tales tecnologías con unos cuantos mecanismos estándar de seguridad empresarial distribuida. Como hemos podido ver este trabajo, el alcance de tales mecanismos puede ser mínimo o muy amplio, dependiendo de la tecnología de que trate. Aunque a Java todavía le queda mucho camino por recorrer para proporcionar un entorno estándar seguro para algunas tecnologías empresariales Java, existe una infraestructura suficiente para que los desarrolladores de aplicaciones empiecen a implementar aplicaciones empresariales seguras distribuidas en algunos casos. En este trabajo hemos explorado los distintos mecanismos que tienen a su disposición los desarrolladores de aplicaciones en este sentido. %LEOLRJUDItD Seguridad en Java – Edición Especial – Prentice Hall – J. Jaworski – P. J. Perrone. Client/Server programming with Java and Corba 2nd. Ed.- J. Wiley – R. Orfali – D. Harkeyl. Java 2 – Manual de usuario y Tutorial 2da Edición – Alfaomega Ra-Ma – Agustín Froufe. La Biblia del Java – Anaya – L. Vanhelsuwé. Aplicaciones de negocios en Java – Compumagazine – J. Bourdette. El lenguaje de programación Java – Addison Wesley – K. Arnold – J. Golsing. Java: biblioteca del programador – McGraw-Hill – S. Sam Lalani – K. Jamsa. Como programar en Java – Prentice-Hall – H. M. Deitel – P.J. Deitel. 13