Pues yo sigo poniendo articulitos traducidos por el que os escribe. Son pildorillas de información técnica sobre tecnologías (Java) que creo que van bien para saber que existen y para qué sirven. Esta vez es un artículo sobre las annotations en aplicaciones web, que podréis encontrar en Enterprise Tech Tips de Sun y que está escrito por Shing Wai Chan.
Bueno, vamos a empezar con Using Annotations in Web Applications.
La quinta versión de Java EE (Enterprise Edition) introdujo las llamadas “annotations”, una forma de simplificar el desarrollo y configuración de aplicaciones empresariales. En el artículo Using Security Annotations in Enterprise Beans, publicado el 31 de marzo pasado, se mostró como usar las “anotaciones” para simplificar el desarrollo de aplicaciones seguras que usan enterprise beans. Algunas de las annotations de Java EE 5 son específicar para las aplicaciones web. Ejemplos de este tipo son @Resource, @EJB, y @WebServiceRef. Otras anotaciones, como @RunAs y @DeclareRoles, están relacionados con la seguridad. Las anotaciones que se relacionan con la seguridad fueron presentados en la “propina” Using Security Annotations in Enterprise Beans.
Aunque se pueden especificar anotaciones en varios componentes de una aplicación web, no se puede especificar una anotación en una página JSp (JavaServer Pages). Sin embargo, las annotations están soportadas en librerías web. Esto quiere decir que se pueden especificar anotaciones en librerías de tags y filtros de servlets, entre otros sitios. Esto nos suministra un modo de dar seguridad a páginas web y servlets, aunque eso sí, es necesario especificar la información de seguridad adecuada en el fichero web.xml de la aplicación web.
Este artículo muestra como hacer una aplicación web segura con servlets y páginas JSP. Configurando el fichero web.xml de la aplicación web, puedes proteger los servlets y páginas JSP que están por encima de una “Secure Sockets Layer connection”. Este es un método común en un entorno web de producción.
Este artículo va acompañado de una ejemplo de paquete de aplicación web. Los ejemplos de código del artículo están sacados del código fuente de ejemplo.
El Servlet
Vamos a empezar examinando el servlet de la aplicación web. En este ejemplo, el servlet invoca un bean de empresa (en este caso, un bean de sesión sin estado) con una interfaz local SlessLocal. El servlet pasa un objeto de mensaje como un atributo de la petición y lo redirige a la página JSP, display.jsp. Aquí tenemos la mayor parte del código del servlet:
@DeclareRoles({"arole"})
@RunAs("myrole")
public class TestServlet extends HttpServlet {
private @EJB SlessLocal slessLocal;
public void service(
HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
if (req.isUserInRole("arole")) {
String message = slessLocal.hello("World");
req.setAttribute("EJB_MESSAGE", message);
}
RequestDispatcher rd =
req.getRequestDispatcher("display.jsp");
rd.forward(req, resp);
}
}
La anotación @EJB se usa para buscar un enterprise bean con la interfaz correspondiente de modo que el bean pueda ser usado por el servlet. La anotación @DeclareRoles define el rol que usará HttpServletRequest.isUserInRole(String role). El método isUserInRole determina si el usuario autenticado está incluido en el rol especificado. En este caso, sólo un usuario con el rol “arole” hará que el servlet devuelva el string de mensaje y los establezca como un atributo de HttpServletRequest.
La annotation @RunAs especifica que el rol “myrole” debería ser usado para acceder al método SlessLocal.hello(String message) del bean de empresa.
El Enterprise Bean
Aquí está la mayor parte del código del bean de sesión sin estado:
@Stateless
@Local({SlessLocal.class})
public class SlessBean implements SlessLocal {
@RolesAllowed(value={"myrole"})
public String hello(String message) {
return "Hello, " + message + ", " + new Date();
}
}
Hay que notar que el método hello está protegido por el uso de la anotación @RolesAllowed. La anotación especifica que sólo los usuarios autenticados en el rol “myrole” pueden acceder al método hello.
La JSP y la librería de Tags
La página JSP, display.jsp, invoca una acción de una librería de tags para JSP y pasa el atributo EJB_MESSAGE como un parámetro del HttpServletRequest. Aquí tenéis un trozo del código de la página JSP:
<%@taglib prefix="di"
uri="http://java.sun.com/techtip/webann/test-taglib"%>
...
<di:displayInfo ejbMessage="${requestScope.EJB_MESSAGE}"/>
...
El tag handler para el tag lee el valor del parámetro ejbMessage y lo muestra en HTML. Además muestra el timeout de login para el DataSource. Aquí está el pertinente código del tag handler:
public class DisplayInfoTagHandler extends SimpleTagSupport {
private @Resource(name="jdbc/__default") DataSource ds;
...
public void doTag() throws JspException, IOException {
try {
JspWriter out = getJspContext().getOut();
int timeout = ds.getLoginTimeout();
if (ejbMessage != null && ejbMessage.length() > 0)
{
out.println(
"<li> Ejb Message: " + ejbMessage);
}
out.println(
"<li> DataSource login timeout: " + timeout);
...
}
public void setEjbMessage(String ejbMessage) {
this.ejbMessage = ejbMessage;
}
}
La anotación @Resource en el tag handler se usa para buscar el DataSource con el nombre JNDI, “jdbc/__default”. Este nombre JNDI corresponde a la base de datos Derby por defecto. Si se quiere acceder a la conexión de la base de datos, se puede añadir el código ds.getConnection() al tag handler.
Nótese también que el tag handler define un método “setter” para el parámetro ejbMessage.
Dando seguridad al Servlet y a la página JSP
Este ejemplo da seguridad a la aplicación mediante el requerimiento de dar un username y un password y usando SSL en la capa de transporte. El username y el password se envían como texto plano. No hay nacesidad de modificar el código Java o la página JSP de la aplicación. Para asegurar el servlet y la JSP lo que hay que hacer es configurar el web.xml tal que así:
<security-constraint>. Esto protege una URL de modo que un rol especificado pueda acceder a ella. Nótese que se pueden definir uno o más métodos HTTP a los que la restricción de seguridad se puede aplicar usando elementos <http-method> en la restricción de seguridad. Si quieres que la restricción de seguridad se aplique a todos los métodos HTTP, simplemente no uses ningún elemento <http-method>.<user-data-constraint> y dentro de él un elemento <transport-guarantee>. Establece el valor del elemento <transport-guarantee> a CONFIDENTIAL.<login-config> y dentro de él un elemento <auth-method>. Establece el valor de este elemento a BASIC.Aquí tenéis un trozo del código del web.xml:
<security-constraint>
< web-resource-collection>
<web-resource-name>Servlet Application
</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>ttrole</role-name>
</auth-constraint>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL
</transport-guarantee>
</user-data-constraint>
</security-constraint>
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>default</realm-name>
</login-config>
<security-role>
<role-name>ttrole</role-name>
</security-role>
En este ejemplo, sólo los usuarios del rol “ttrole” pueden acceder al servlet y a la JSP. Es más, sólo los usuarios que también son del rol “arole” podrán llamar al bean SlessLocal.
El entorno Java EE usa los roles para autorización. Sin embargo, en muchos sistemas operativos, los usuarios están asociados a grupos. La correspondencia rol-seguridad da un enlace entre los conceptos de roles de usuarios y grupos. En un servidor de aplicaciones para Java EE 5 como Sun Java System Application Server del Java EE 5 SDK, se define el security-role-mapping en el fichero sun-application.xml. Aquí tenemos un ejemplo:
<sun-application>
<security-role-mapping>
<role-name>myrole</role-name>
<principal-name>myuser</principal-name>
</security-role-mapping>
<security-role-mapping>
<role-name>ttrole</role-name>
<group-name>ttgroup</group-name>
</security-role-mapping>
<security-role-mapping>
<role-name>arole</role-name>
<principal-name>ttuser</principal-name>
</security-role-mapping>
</sun-application>
Ejecutar el código de ejemplo
<appserv_install_dir>/bin/asadmin start-domain domain1 donde <appserv_install_dir> es el directorio dónde se haya instalado el Sun Java System Application Server.User Id: ttuser
Group List: ttgroup
New Password: ttpassword
Confirm New Password: ttpassword
Una vez creado el usuario, crea un segundo usuario del mismo grupo entrando la siguiente info:
User Id: ttuser2
Group List: ttgroup
New Password: ttpassword
Confirm New Password: ttpassword
Esto construye el fichero ear, web.ear, y lo pone en el directorio webann/dist.
También puedes desplegar el fichero ear a través de la consola de administración así:
Además puedes desplegar el fichero ear introduciendo el siguiente comando en la linea de comandos:
asadmin deploy webann.ear
Hello, ttuser
Ejb Message: Hello, World, Sat Jun 30 12:04:46 PDT 2007
DataSource login timeout: 0
Si te “logeas” como ttuser2, deberías ver algo como:
Hello, ttuser2
DataSource login timeout: 0
La diferencia de la respuesta se debe a los roles de cada uno de los usuarios. El usuario ttuser tiene los roles “ttrole” y “arole”. El usuario ttuser2 tiene sólo el rol “ttrole”. En esta aplicación, sólo los usuarios del rol “arole” están autorizados a invocar el método SlessLocal.hello(String message), el método que crea el mensaje “Hello, World”.
Cuando finalizas la aplicación, la puedes replegar (desinstalar) y eliminar los usuarios creados así:
Y ya está, aquí tenemos otro pequeño ejemplo de uso de Java EE. A ver si le sirve de utilidad a alguien.
Fuente: Enterprise Tech Tips
[…] Aquí tenéis el enlace al artículo. […]