DEPARTAMENTO DE SISTEMAS Arquitectura de Software Session Beans ISIS3702 Agenda DEPARTAMENTO DE SISTEMAS • Anotaciones • Java Naming Directory Interface (JNDI) • Session Beans Anotaciones DEPARTAMENTO DE SISTEMAS Evitar la división de artefactos programación en varios archivos Implementación – Interface Archivos descriptores separados de Definir un mecanismo estándar para anotar archivos de clases Java Anotaciones DEPARTAMENTO DE SISTEMAS Las anotaciones no afectan directamente la semántica de un programa. (no son usadas por la JVM) Sí afectan cómo el código es usado por herramientas, librerías y frameworks. Pueden ser leídas del código fuente, archivos de clase o durante la ejecución Anotaciones DEPARTAMENTO DE SISTEMAS Una anotación es un tipo especial de modificador y puede ser usada en cualquier lugar que se usen otros modificadores ( como public, static o final) Por convención modificadores Consisten de un signo de arroba (@) seguido del tipo de la anotación y una lista en paréntesis de pares elemento-valor se ponen antes que otros Anotaciones DEPARTAMENTO DE SISTEMAS Atributos public class SomeClass{ @Resource (name=“customerDB”) private DataSource myDb;… } Métodos public class SomeClass{ private DataSource myDb; @Resource (name=“customerDB”) private void setMyDB(…) {...} ... } Clases @Resource (name=“MyMessageQueue” , type=“ConnectionFactor ”) public class SomeClass{ ... } Anotaciones DEPARTAMENTO DE SISTEMAS • Definición o @interface • Tipos o o o Marker Single-Element Multi-value public @interface MyAnnotation { String doSomething(); } @MyAnnotation public void mymethod() { .... } @MyAnnotation ("What to do") public void mymethod() { .... } Anotaciones DEPARTAMENTO DE SISTEMAS • Anotation Driven Code Instrumentation o o o o o Annotation Processing Tool (APT) Utilidad para procesar anotaciones Incluye un API reflexivo No ermite modificar le código fuente Se puede modificar el byte code Anotaciones DEPARTAMENTO DE SISTEMAS public class SimpleTransformer { public static void main(String[] args) throws Exception { SimpleTransformer transformer = new SimpleTransformer(); transformer.transform(args[0], args[1]); } public void transform(String input, String output) throws IOException { writeClassData(transform(readClassData(input)), output); } private byte[] transform(byte[] code) { ClassReader reader = new ClassReader(code); ClassNode classNode = new ClassNode(); reader.accept(classNode, true); classNode.fields.add(new FieldNode(Opcodes.ACC_PUBLIC, "myNewField", "I", null, null)); ClassWriter writer = new ClassWriter(false); classNode.accept(writer); return writer.toByteArray(); } } Tomado de : http://llhours.free.fr/drupal/?q=node/15 Agenda DEPARTAMENTO DE SISTEMAS • Anotaciones • Java Naming Directory Interface (JNDI) • Session Beans JNDI DEPARTAMENTO DE SISTEMAS Acceso desde un componente a otros componentes o recursos (e.g., bases de datos) Un servlet puede invocar métodos remotos de un enterprise bean que consulta información de una bd JNDI es un servicio de nombres que permite a un componente localizar otros componentes o recursos Habilita a las aplicaciones para acceder múltiples servicios de nombres y de directorios. Por ejemplo servicios como LDAP, NDS,DNS, y NIS. Ofrece los métodos de Asociar un nombre con un objeto (binding) Buscar un objeto (lookup) El uso de JNDI en aplicaciones Java EE permite almacenar o consultar cualquier objeto de java: acceso a sistemas y aplicaciones Legado JNDI DEPARTAMENTO DE SISTEMAS Un administrador crea un recurso en un namespace de JNDI En el servidor de aplicaciones se pueden crear recursos con la consola de administración o el comando asadmin Las aplicaciones utilizan anotaciones para acceder a los recursos. Cuando una aplicación utiliza la “inyección” del recurso, el servidor de aplicaciones invoca el API JNDI (@Resource) La aplicación puede hacer llamados directos del API JNDI Un recurso y su nombre JNDI son ligados por el servicio de nombres Un recurso nuevo es creado en JNDI con la asociación del nombre del recurso en el namespace de JNDI (bind del recurso) Namespace: conjunto de todos los nombres de un servicio de nombres JNDI DEPARTAMENTO DE SISTEMAS • @EJB o o Declaración del atributo Método Setter • Atributos Opcionales o beanName o beanInterface o Nombre de la clase Ejb-name si el EJB tiene un descriptor XML Interface local o remota mappedName Nombre JNDI JNDI DEPARTAMENTO DE SISTEMAS Partes de un @Resource name: nombre del recurso en JNDI type: el tipo (Java) del recurso authenticationType: tipo de autenticación para utilizar el recurso shareable: indica si el recurso puede ser compartido mappedName: nombre específico de la implementación que indica que el recurso puede ser mapeado a description: descripción del recurso Ejemplos de estilos de inyección: atributos, métodos y clases Atributos: public class SomeClass { @Resource(name="customerDB") private javax.sql.DataSource myDB; ... } Métodos public class SomeClass { private javax.sql.DataSource myDB; ... @Resource(name="customerDB") private void setMyDB(javax.sql.DataSource ds) { myDB = ds; } Clases @Resource(name="myMessageQueue", type="javax.jms.ConnectionFactory") public class SomeMessageBean { …} JNDI - Ejemplo DEPARTAMENTO DE SISTEMAS Acceso a una base de datos con el API JDBC: recurso JDBC con información sobre Servidor de BD Nombre de la BD Protocolo de red utilizado para la comunicación Un objeto DataSource es una fábrica de conexiones de una fuente de datos específica. El método getConnection retorna una conexión física a la fuente de datos Si el objeto DataSource es registrado con JNDI, una aplicación puede utilizar el API JNDI (lookup) para obtener el objeto y posteriormente conectarse a la fuente de datos Las aplicaciones utilizando el API de persistencia especifican la fuente de datos en el archivo persistence.xml <jta-data-source>jdbc/MyOrderDB</jta-data-source> Este punto es el único que referencia algo sobre el objeto JDBC JNDI DEPARTAMENTO DE SISTEMAS • Los servicios de nombres de Java EE proveen ambientes de nombres JNDI a las aplicaciones cliente, enterprise beans, y componente web • Un naming environment permite personalizar a un componente sin acceder o cambiar el código fuente de los componentes • Un contenedor implementa el ambiente de los componentes como un contexto de nombres • Contexto es un objeto cuyo estado tiene asociados un conjunto de relaciones entre nombres y objetos (bindings) • Un contexto tiene asociado una convención de nombres • Contexto inicial es el punto de partida para hacer las operaciones • En JNDI todas las operaciones son realizadas en un contexto JNDI DEPARTAMENTO DE SISTEMAS Un componente Java EE puede localizar su contexto de nombres con JNDI Un componente puede crear un objeto javax.naming.InitialContext y buscar su contexto bajo el nombre de java:comp/env. Un componente Java EE puede acceder nombres provistos por el sistema (named system-provided) y objetos definidos por los usuarios (user-defined objects) Nombres de objetos provistos por el sistema (e.g., objetos JTA) son almacenados en el contexto java:comp/env Según el tipo de objeto a definir por el usuario el subcontexto para registrarlo varía Enterprise beans: java:comp/env/ejb JDBC DataSource: java:comp/env/jdbc JNDI DEPARTAMENTO DE SISTEMAS Ejemplo con propiedades del ambiente Hashtable env = new Hashtable(); env.put(Context.PROVIDER_URL, args[2]); //rmi://localhost:1099 Context ctxt = new InitialContext(env); Compute comp = (Compute) ctxt.lookup(name); Ejemplo con archivo de configuración de las propiedades Context initial = new InitialContext(); Object objref = initial.lookup("java:comp/env/ejb/SimpleConverter”); Archivo build.xml <target name="run" depends="buildjar"> <java fork="true" classname="client.ComputePi"> <classpath path="${build}" /> <classpath path="${compute}" /> … <sysproperty key="java.naming.factory.initial" value="com.sun.jndi.rmi.registry.RegistryContextFactory" /> <sysproperty key="java.naming.provider.url" value="rmi://${hostname}:${port}" /> </java> </target> JNDI DEPARTAMENTO DE SISTEMAS Las propiedades del ambiente JNDI se deben configurar de acuerdo con las características del proveedor del servicio que se va a utilizar Las propiedades se clasifican en: Estándares (java.naming……): java.naming.factory.initial Específicas del servicio (java.naming.service……): java.naming.corba.orb Característica específica (java.naming.feature….): java.naming.security.sasl Especificas del proveedor: com.sun.jndi.ldap.trace.ber JNDI DEPARTAMENTO DE SISTEMAS java.naming.factory.initial nombre de la clase de la fábrica del contexto inicial La clase debe implementar la interface InitialContextFactory Ejemplo valores: com.sun.jndi.ldap.LdapCtxFactory com.sun.jndi.rmi.registry.RegistryContextFactory JNDI DEPARTAMENTO DE SISTEMAS java.naming.provider.url El URL para configurar el proveedor del servicio definido en la propiedad "java.naming.factory.initial" Ejemplo valores: ldap://localhost:389/o=JNDITutorial rmi://localhost:1099 Agenda DEPARTAMENTO DE SISTEMAS • Anotaciones • Java Naming Directory Interface (JNDI) • Session Beans Session Beans DEPARTAMENTO DE SISTEMAS Representa un cliente de la aplicación o una sesión de un cliente Ofrece un conjunto de métodos para la interacción entre un cliente y una aplicación No es compartido entre clientes No es persistente, opuesto a los beans de entidad Session Beans DEPARTAMENTO DE SISTEMAS Con estado (stateful) El estado del bean representa la interacción entre un cliente específico y el bean El estado del bean o conjunto de atributos se mantiene durante toda la sesión del cliente Al terminar la sesión el estado no se conserva El contenedor puede almacenarlos en memoria secundaria Puede implementar servicios web Sin estado (stateless) El estado del bean se conserva únicamente durante la ejecución del método invocado Todo bean tiene el mismo estado antes de ser invocado El contenedor de EJB puede seleccionar cualquier bean para ejecutar un método Es apropiado para brindar la escalabilidad de aplicaciones ya que puede soporta múltiples clientes Nunca son almacenados en memoria secundaria Session Beans DEPARTAMENTO DE SISTEMAS Qué es el estado de un bean de sesión. Dé ejemplos Una clase que representa un bean de sesión sin estado puede tener atributos? El mismo bean de sesión puede implementarse con o sin estado?. Dé un ejemplo En la hoja de trabajo entregada, identifique las diferencias entre un bean de sesión con y sin estado Session Beans DEPARTAMENTO DE SISTEMAS Un bean de sesión requiere una clase Todo bean de sesión que permita su acceso remoto debe tener una interfaz de negocios remota Los métodos de negocio El nombre no puede comenzar con ejb. Esto evita conflictos con los métodos callback (ejbCreate, ejbActivate) Deben ser públicos Si el bean para su acceso de forma remota utilizó una interfaz de negocios remota, los tipos de retorno y los parámetros deben ser tipos válidos de Java RMI No pueden ser ni static ni final Para indicar problemas como incapacidad para conectarse a la BD, debe incluir throw javax.ejb.EJBException Un bean de sesión para brindar los requerimientos funcionales de una aplicación puede necesitar de clases helper (ManejoExcepciones y verificaciones) Session Beans DEPARTAMENTO DE SISTEMAS Ejemplo - Intermediario El bean representa un carro de compras en una tienda en línea El cliente puede adicionar, borrar o consultar el contenido del carro de compras Archivos: Interfaz remota (Cart.java) Clase enterprise bean (CartBean.java) Clase cliente (CartClient.java) Clases Helper (BookException.java and IdVerifier.java). Session Beans - Ejemplo cart.java DEPARTAMENTO DE SISTEMAS import java.util.List; import javax.ejb.Remote; @Remote Métodos del negocio public interface Cart { public void initialize(String person) throws BookException; public void initialize(String person, String id) throws BookException; public void addBook(String title); public void removeBook(String title) throws BookException; public List<String> getContents(); public void remove(); } Session Beans - cartBean.java DEPARTAMENTO DE SISTEMAS Clase bean del ejemplo Implementa la interface de negocio Tiene la anotación @Stateful. Implementa los métodos de negocios definidos en la interface de negocios Los beans con estado adicionalmente Pueden implementar cualquier método de callback, anotados con @PostConstruct, @PreDestroy, @PostActivate o @PrePassivate Implementan cualquier método opcional anotado con @Remove Session Beans - cartBean.java (2) DEPARTAMENTO DE SISTEMAS import javax.ejb.Remove; import javax.ejb.Stateful; @Stateful public class CartBean implements Cart { String customerName; String customerId; List<String> contents; public void initialize(String person) throws BookException { if (person == null) { throw new BookException("Null person not allowed."); } else { customerName = person; } customerId = "0"; contents = new ArrayList<String>(); } //id: parametro String id de initialize IdVerifier idChecker = new IdVerifier(); if (idChecker.validate(id)) { customerId = id; } else { throw new BookException("Invalid id: " + id); } public void addBook(String title) { contents.add(title); } @Remove public void remove() { contents = null; } Session Beans - Anotaciones DEPARTAMENTO DE SISTEMAS Interface @Remote: indica que se trata de una interfaz de negocio remota @Local: acceso al bean de forma local únicamente Clase @stateless similar a @stateful /* bean de sesión con estado */ Indica que el bean de sesión es sin estado Dependiendo del contenedor Se crea el stub del bean Registra en JNDI el bean con el nombre lógico "java:comp/env/ejb/ nombreBean“ o con un nombre dado en la anotación @EJB Aplica para interfaces remotas únicamente Genera el lookup del bean de sesión en JNDI con el nombre "java:comp/ env/ejb/nombreBean“ En serviciosCliente.java @EJB(name = "co.com.uniandes.ejemplo.servicios.IServiciosProducto") private IServiciosProducto serviciosProducto; @Resource Inyección de recursos @Resource(name="jdbc/sqetestDB",type=javax.sql.DataSource.class) public javax.sql.DataSource myTestDB; Session Beans - Anotaciones DEPARTAMENTO DE SISTEMAS • • • • • @PostConstruct @PrePassivate @PreDestroy @PostActivate @Init Session Beans DEPARTAMENTO DE SISTEMAS Métodos de Callback son invocados por el contenedor relacionados con el ciclo de vida del bean Deben ser públicos, sin retorno (void), y sin parámetros. Utilizan las siguientes anotaciones @PostConstruct: invocado sobre una instancia recientemente creada después de la inyección (o JNDI lookup) de todas las dependencias y antes de la invocación del primer método (javax.annotation.PostConstruct) @PreDestroy: invocado luego de que un método anotado con @Remove ha terminado y antes de que el contenedor elimine la instancia del bean (javax.annotation.PreDestroy) @PrePassivate: invocado antes de que el contenedor desactive (passivave) el bean, el contenedor elimina temporalmente el bean y lo salva en memoria secundaria (javax.ejb.PrePassivate) @PostActivate: invocado después de que el contenedor mueve el bean de memoria secundaria a estado activo (active) (javax.ejb.PostActivate) Ciclo de vida bean con estado DEPARTAMENTO DE SISTEMAS El método remove es el único que es invocado directamente por el cliente El contendor decide desactivar el bean El cliente inicia el ciclo de vida obteniendo una referencia al bean de sesión -stateful 1. 2. El cliente invoca algún método del negocio durante la desactivación Ciclo de vida bean sin estado DEPARTAMENTO DE SISTEMAS El cliente inicia el ciclo de vida obteniendo una referencia al bean de sesión -stateful 1. JEE – EJB3/ Security DEPARTAMENTO DE SISTEMAS • EJB3 Security o El contenedor ofrece un servicio de seguridad para toda la aplicación o Es posible configurar los permisos de usuario para cada llamado de un método usando solamente anotaciones o Basado en el Java Authentication Authorization Service (JAAS) and JEE – EJB3/ Security DEPARTAMENTO DE SISTEMAS JEE – EJB3/ Security DEPARTAMENTO DE SISTEMAS • EJB3 Security o Nombres de Usuarios y Passwords Servidores LDAP Servidores de Bases de Datos Archivos Texto (properties) users.properties roles.properties Debe estar en el path de la aplicación admin=jboss user=ejb3 admin=AdminUser,RegularUser user=RegularUser JEE – EJB3/ Security DEPARTAMENTO DE SISTEMAS • EJB3 Security o o o o Annotations Sirven para especificar dónde encontrar la lista de roles y passwords Definen que roles y usuarios están permitidos para ejecutar un método @SecurityDomain (“other”) o @RolesAllowed() o Anota métodos que no serán verificados con restricciones de seguridad @DenyAll o Especifica los roles permitidos a ejecutar cada métodos @PermitAll o Indica que se usaran los archivos de properties para el manejo de la seguridad Ningún rol está autorizado para llamar este método DeclareRoles Roles definidos en una clase JEE – EJB3/ Security DEPARTAMENTO DE SISTEMAS public interface Calculator { int add(int x, int y); int subtract(int x, int y); int divide(int x, int y); } @Stateless @SecurityDomain("other") public class CalculatorBean implements Calculator { @PermitAll @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) public int add(int x, int y) { return x + y; } @RolesAllowed({"student"}) public int subtract(int x, int y) { return x - y; } @RolesAllowed({"teacher"}) public int divide(int x, int y) { return x / y; } } JEE – EJB3/ Security DEPARTAMENTO DE SISTEMAS public class Main { public static void main(String[] args) throws Exception { EJB3StandaloneBootstrap.boot(null); EJB3StandaloneBootstrap.deployXmlResource("security-beans.xml"); EJB3StandaloneBootstrap.scanClasspath(); // Establish the proxy with an incorrect security identity Properties env = new Properties(); env.setProperty(Context.SECURITY_PRINCIPAL, "kabir"); env.setProperty(Context.SECURITY_CREDENTIALS, "invalidpassword"); env.setProperty(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.security.jndi.JndiLoginInitialContextFactory"); InitialContext ctx = new InitialContext(env); Calculator calculator = (Calculator) ctx.lookup("CalculatorBean/local"); System.out.println("Kabir is a student."); System.out.println("Kabir types in the wrong password"); try { System.out.println("1 + 1 = " + calculator.add(1, 1)); } catch (EJBAccessException ex) { System.out.println("Saw expected SecurityException: " + ex.getMessage()); } JEE – EJB3/ Security DEPARTAMENTO DE SISTEMAS System.out.println("Kabir types in correct password."); System.out.println("Kabir does unchecked addition."); // Re-establish the proxy with the correct security identity env.setProperty(Context.SECURITY_CREDENTIALS, "validpassword"); ctx = new InitialContext(env); calculator = (Calculator) ctx.lookup("CalculatorBean/local"); System.out.println("1 + 1 = " + calculator.add(1, 1)); System.out.println("Kabir is not a teacher so he cannot do division"); try { calculator.divide(16, 4); } catch (javax.ejb.EJBAccessException ex) { System.out.println(ex.getMessage()); } System.out.println("Students are allowed to do subtraction"); System.out.println("1 - 1 = " + calculator.subtract(1, 1)); } } Pruebas Unitarias – EJB3 DEPARTAMENTO DE SISTEMAS @Stateful(name = "Movies") public class MoviesImpl implements Movies { @PersistenceContext(unitName = "movie-unit", type = PersistenceContextType.EXTENDED) private EntityManager entityManager; @RolesAllowed({"Employee", "Manager"}) public void addMovie(Movie movie) throws Exception { entityManager.persist(movie); } @RolesAllowed({"Manager"}) public void deleteMovie(Movie movie) throws Exception { entityManager.remove(movie); } @PermitAll @TransactionAttribute(TransactionAttributeType.SUPPORTS) public List<Movie> getMovies() throws Exception { Query query = entityManager.createQuery("SELECT m from Movie as m"); return query.getResultList(); } } Tomado de: http://openejb.apache.org/3.0/testing-security-example.html Pruebas Unitarias – EJB3 DEPARTAMENTO DE SISTEMAS public class MovieTest extends TestCase { private Context context; protected void setUp() throws Exception { Properties p = new Properties(); p.put(Context.INITIAL_CONTEXT_FACTORY, "org.apache.openejb.client.LocalInitialContextFactory"); p.put("movieDatabase", "new://Resource?type=DataSource"); p.put("movieDatabase.JdbcDriver", "org.hsqldb.jdbcDriver"); p.put("movieDatabase.JdbcUrl", "jdbc:hsqldb:mem:moviedb"); p.put("movieDatabaseUnmanaged", "new://Resource?type=DataSource"); p.put("movieDatabaseUnmanaged.JdbcDriver", "org.hsqldb.jdbcDriver"); p.put("movieDatabaseUnmanaged.JdbcUrl", "jdbc:hsqldb:mem:moviedb"); p.put("movieDatabaseUnmanaged.JtaManaged", "false"); context = new InitialContext(p); } Tomado de: http://openejb.apache.org/3.0/testing-security-example.html Pruebas Unitarias – EJB3 DEPARTAMENTO DE SISTEMAS public void testAsManager() throws Exception { Caller managerBean = (Caller) context.lookup("ManagerBeanLocal"); managerBean.call(new Callable() { public Object call() throws Exception { Movies movies = (Movies) context.lookup("MoviesLocal"); movies.addMovie(new Movie("Quentin Tarantino", "Reservoir Dogs", 1992)); movies.addMovie(new Movie("Joel Coen", "Fargo", 1996)); movies.addMovie(new Movie("Joel Coen", "The Big Lebowski", 1998)); List<Movie> list = movies.getMovies(); assertEquals("List.size()", 3, list.size()); for (Movie movie : list) { movies.deleteMovie(movie); } assertEquals("Movies.getMovies()", 0, movies.getMovies().size()); return null; } }); } Tomado de: http://openejb.apache.org/3.0/testing-security-example.html Pruebas Unitarias – EJB3 DEPARTAMENTO DE SISTEMAS public void testAsEmployee() throws Exception { Caller employeeBean = (Caller) context.lookup("EmployeeBeanLocal"); employeeBean.call(new Callable() { public Object call() throws Exception { Movies movies = (Movies) context.lookup("MoviesLocal"); movies.addMovie(new Movie("Quentin Tarantino", "Reservoir Dogs", 1992)); movies.addMovie(new Movie("Joel Coen", "Fargo", 1996)); movies.addMovie(new Movie("Joel Coen", "The Big Lebowski", 1998)); List<Movie> list = movies.getMovies(); assertEquals("List.size()", 3, list.size()); for (Movie movie : list) { try { movies.deleteMovie(movie); fail("Employees should not be allowed to delete"); } catch (EJBAccessException e) { // Good, Employees cannot delete things } } assertEquals("Movies.getMovies()", 3, movies.getMovies().size()); return null; } }); } Tomado de: http://openejb.apache.org/3.0/testing-security-example.html Pruebas Unitarias – EJB3 DEPARTAMENTO DE SISTEMAS public void testUnauthenticated() throws Exception { Movies movies = (Movies) context.lookup("MoviesLocal"); try { movies.addMovie(new Movie("Quentin Tarantino", "Reservoir Dogs", 1992)); fail("Unauthenticated users should not be able to add movies"); } catch (EJBAccessException e) { // Good, guests cannot add things } try { movies.deleteMovie(null); fail("Unauthenticated users should not be allowed to delete"); } catch (EJBAccessException e) { // Good, Unauthenticated users cannot delete things } try { // Read access should be allowed List<Movie> list = movies.getMovies(); } catch (EJBAccessException e) { fail("Read access should be allowed"); }} Tomado de: http://openejb.apache.org/3.0/testing-security-example.html Pruebas Unitarias – EJB3 DEPARTAMENTO DE SISTEMAS public static interface Caller { public <V> V call(Callable<V> callable) throws Exception; } /** * This little bit of magic allows our test code to execute in * the desired security scope. * <p/> * The src/test/resource/META-INF/ejb-jar.xml will cause this * EJB to be automatically discovered and deployed when * OpenEJB boots up. */ @Stateless @RunAs("Manager") public static class ManagerBean implements Caller { public <V> V call(Callable<V> callable) throws Exception { return callable.call(); } } @Stateless @RunAs("Employee") public static class EmployeeBean implements Caller { public <V> V call(Callable<V> callable) throws Exception { return callable.call(); } }} Tomado de: http://openejb.apache.org/3.0/testing-security-example.html Pruebas Unitarias – EJB3 DEPARTAMENTO DE SISTEMAS users.properties bschuchert=password msmith=password dnunn=password student=password roles.properties bschuchert=admin msmith=admin dnunn=admin student=user Tomado de: http://schuchert.wikispaces.com/EJB3+Tutorial+6+-+Security Pruebas Unitarias – EJB3 DEPARTAMENTO DE SISTEMAS @Stateless @SecurityDomain("other") public class AccountInventoryBean implements AccountInventory { @PersistenceContext(unitName = "tolltag") private EntityManager em; public EntityManager getEm() { return em; } /** * Only allow users that can play the role of admin to access this method. */ @RolesAllowed( { "admin" }) public void createAccount(final Account account) { getEm().persist(account); } @RolesAllowed( { "admin", "user" }) public Account findAccountById(final Long id) { return getEm().find(Account.class, id); } Tomado de: http://schuchert.wikispaces.com/EJB3+Tutorial+6+-+Security Pruebas Unitarias – EJB3 DEPARTAMENTO DE SISTEMAS /** * The default access is PermitAll if you do not otherwise specify the roles * allowed. You can change this default by applying the RolesAllowed * annotation to the class instead of a method. */ @PermitAll public void removeTag(final String tagNumber) { final TollTag tt = (TollTag) getEm().createNamedQuery( "TollTag.byTollTagNumber").setParameter("tagNumber", tagNumber) .getSingleResult(); final Account account = tt.getAccount(); account.removeTollTag(tt); tt.setAccount(null); getEm().remove(tt); getEm().flush(); } public void removeAccountById(final Long id) { final Account toRemove = findAccountById(id); getEm().remove(toRemove); getEm().flush(); } } Tomado de: http://schuchert.wikispaces.com/EJB3+Tutorial+6+-+Security Pruebas Unitarias – EJB3 DEPARTAMENTO DE SISTEMAS public class AccountInventoryBeanTest { private static final String WRONG_ACCOUNT = "this account does not exist"; private static final String WRONG_PASSWORD = "this is the wrong password"; private static final String USER_ACCOUNT = "student"; private static final String ADMIN_ACCOUNT = "bschuchert"; private static final String PASSWORD = "password"; @BeforeClass public static void initContainer() { JBossUtil.startDeployer(); } public InitialContext getInitialContextFor(final String user, final String password) throws NamingException { final Properties p = new Properties(); p.setProperty(Context.SECURITY_PRINCIPAL, user); p.setProperty(Context.SECURITY_CREDENTIALS, password); p.setProperty(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.security.jndi.JndiLoginInitialContextFactory"); return new InitialContext(p); } Tomado de: http://schuchert.wikispaces.com/EJB3+Tutorial+6+-+Security Pruebas Unitarias – EJB3 DEPARTAMENTO DE SISTEMAS public static TollTag instantiateTollTag() { final TollTag tt = new TollTag(); tt.setTagNumber("1234567890"); return tt; } public static Vehicle instantiateVehicle() { return new Vehicle("Subaru", "Outback", "2001", "YBU 155"); } public static Account instantiateAccount() { final Account account = new Account(); account.addTollTag(instantiateTollTag()); account.addVehicle(instantiateVehicle()); return account; } private void createAccountUsing(final String userName, final String password) throws Exception { final Account account = instantiateAccount(); final InitialContext ctx = getInitialContextFor(userName, password); AccountInventory bean = (AccountInventory) ctx .lookup("AccountInventoryBean/local"); bean.createAccount(account); bean.removeAccountById(account.getId()); } Pruebas Unitarias – EJB3 DEPARTAMENTO DE SISTEMAS @Test public void successfulCreateAccount() throws Exception { createAccountUsing(ADMIN_ACCOUNT, PASSWORD); } @Test(expected = SecurityException.class) public void unsuccessfulCreateAccountUserNotInRoll() throws Throwable { try { createAccountUsing(USER_ACCOUNT, PASSWORD); } catch (EJBAccessException e) { throw e.getCause(); } } @Test(expected = FailedLoginException.class) public void unsuccessfulCreateAccountWrongPassowrd() throws Throwable { try { createAccountUsing(ADMIN_ACCOUNT, WRONG_PASSWORD); } catch (Exception e) { throw e.getCause(); } } Tomado de: http://schuchert.wikispaces.com/EJB3+Tutorial+6+-+Security Pruebas Unitarias – EJB3 DEPARTAMENTO DE SISTEMAS @Test(expected = FailedLoginException.class) public void unsuccessfulCreateAccountWrongUser() throws Throwable { try { createAccountUsing(WRONG_ACCOUNT, PASSWORD); } catch (Exception e) { throw e.getCause(); } } @Test(expected = FailedLoginException.class) public void unsuccessfulNoCredentials() throws Throwable { try { createAccountUsing("", ""); } catch (EJBAccessException e) { throw e.getCause(); } } Tomado de: http://schuchert.wikispaces.com/EJB3+Tutorial+6+-+Security Session Beans DEPARTAMENTO DE SISTEMAS • Material preparado por o o o 56 María del Pilar Villamil Nicolás López Darío Correal Referencias DEPARTAMENTO DE SISTEMAS [1] Rozanski N, Woods E. “Software Systems Architecture” AddisonWesley. 2005 [2] Documenting Component and Connector Views with UML 2.0, Technical Report, ESC-TR-2004-08 [3] Gary McGraw. “Software Security – Building Security In” AddisonWesley. 2005 [4] Greg Hoglund, Gary McGraw, “Exploiting Software – How to Break Code” Addison-Wesley, 2004 [5] ISO/IEC 15408-2:2005 57