viernes, 4 de junio de 2010

Realms(Dominios) en Glassfish y autenticación con formularios

Para este ejemplo estoy utilizando Netbeans 6.8, Glassfish V3, JDK1.6 y Ubuntu 9.10 Karmic Koala
Como primer paso, debemos crear un Realm(Dominio) en Glassfish:
Bajo Security damos click en Realms y damos click sobre New:
Ahi creamos el Realm con la siguiente informacion:
Realm Name:realmexample
Class Name:com.sun.enterprise.security.auth.realm.file.FileRealm
JAAS Context:fileRealm
Key File:${com.sun.aas.instanceRoot}/config/keyfile

y damos click en OK

Luego damos click en realmexample
y luego click en Manage Users

Ahi damos click en New y creamos un usuario con:
UserId:usuario
Group List:Users
y le damos una clave y damos click en OK

Con esto tenemos ya creado un dominio y un usuario.

Ahora vamos a Netbeans 6.8
Aqui tenemos que crear un nuevo proyecto Java EE al que llamaremos PracticaSeguridades



Luego, bajo el proyecto web creamos un Servlet llamado Cliente, bajo el paquete com.web
En la siguiente pantalla marcamos el checkbox "Add information to deployment descriptor" para que nos genere el descriptor web.xml.



Luego modificamos index.jsp al siguiente código:
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>JSP Page</title>
</head>
<body>
<a href="Cliente">Datos Informativos</a><br/>
<a href="logout.jsp">Salir</a>
</body>
</html>


y agregamos tres páginas jsp llamadas error.jsp, login.jsp, logout.jsp, que deben tener el siguiente código:

error.jsp:
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>JSP Page</title>
</head>
<body>
<h1>Nombre de usuario incorrecto <a href="javascript:history.back(1)">Regresar</a></h1>
</body>
</html>

login.jsp:

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Login de Usuario</title>
</head>
<body>
<form method=post action="j_security_check">
Usuario:<input type="text" name= "j_username"/><br/>
Clave:<input type="password" name= "j_password"/><br/>
<input type="submit" name="submit" value="Ingresar"/>
<input type="reset" name="reset" value="Cancelar"/>
</form>
</body>

</html>


logout.jsp:
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>JSP Page</title>
</head>
<body>
<%session.invalidate();%>
<h1>Gracias por probar esta demo, visita <br/>
<a href="http://festintecnologico.blogspot.com/" target="_blank">Festín tecnológico</a></h1>
</body>
</html>


Hecho esto, tenemos que modificar los archivos sun-web.xml y web.xml para colocar las políticas de seguridades.
En este XML unimos el Perfil de usuario de Glassfish(Users) a uno que nosotros creamos en nuestra aplicación web (Usuarios)

en sun-web.xml agregamos las siguientes lineas antes de </sun-web-app>
<security-role-mapping>
<role-name>Usuarios</role-name>
<group-name>Users</group-name>
</security-role-mapping>

Con lo que el archivo sun-web.xml nos queda como:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sun-web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Application Server 9.0 Servlet 2.5//EN" "http://www.sun.com/software/appserver/dtds/sun-web-app_2_5-0.dtd">
<sun-web-app error-url="">
<context-root>/PracticaSeguridades-war</context-root>
<class-loader delegate="true"/>
<jsp-config>
<property name="keepgenerated" value="true">
<description>Keep a copy of the generated servlet class' java code.</description>
</property>
</jsp-config>
<security-role-mapping>
<role-name>Usuarios</role-name>
<group-name>Users</group-name>
</security-role-mapping>
</sun-web-app>

En web.xml definimos que métodos(GET, POST, PUT, etc) se pueden realizar y sobre que recursos y que roles pueden usar esos recursos, para nuestro caso usaremos el rol de "Usuarios" que definimos en sun-web.xml. Tambien definimos que modo de autenticacion usaremos en nuestro caso, es de tipo Form usando la pagina login.jsp

Para web.xml agregamos las siguientes lineas antes de </web-app>
<security-constraint>
<display-name>Confirmacion Identidad</display-name>
<web-resource-collection>
<web-resource-name>PoliticasSeguridad</web-resource-name>
<description/>
<url-pattern>/*</url-pattern>
<http-method>GET</http-method>
<http-method>POST</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>Usuarios</role-name>
</auth-constraint>

</security-constraint>
<login-config>
<auth-method>FORM</auth-method>
<realm-name>realmexample</realm-name>
<form-login-config>
<form-login-page>/login.jsp</form-login-page>
<form-error-page>/error.jsp</form-error-page>
</form-login-config>
</login-config>

Con lo que el archivo nos queda:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
<security-constraint>
<display-name>Confirmacion Identidad</display-name>
<web-resource-collection>
<web-resource-name>PoliticasSeguridad</web-resource-name>
<description/>
<url-pattern>/*</url-pattern>
<http-method>GET</http-method>
<http-method>POST</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>Usuarios</role-name>
</auth-constraint>

</security-constraint>
<login-config>
<auth-method>FORM</auth-method>
<realm-name>realmexample</realm-name>
<form-login-config>
<form-login-page>/login.jsp</form-login-page>
<form-error-page>/error.jsp</form-error-page>
</form-login-config>
</login-config>
</web-app>


Luego, para el proyecto EJB, vamos a crear un nuevo Bean de Session y lo llamaremos EjemploSeguridadBean bajo el paquete com.ejb y marcamos la interface remote de la siguiente manera:



damos click en Finish.

Modificamos los archivos
EjemploSeguridadBeanRemote.java

package com.ejb;

import javax.ejb.Remote;

@Remote
public interface EjemploSeguridadBeanRemote {
String probarSeguridadEJB();
}


EjemploSeguridad.java
En este archivo usamos las anotaciones @RolesAllowed y @DeclareRoles({"Usuarios"}) para indicar que Roles de usuario definidos en sun-web.xml pueden ejecutar esta rutina

package com.ejb;

import javax.annotation.Resource;
import javax.annotation.security.DeclareRoles;
import javax.annotation.security.RolesAllowed;
import javax.ejb.SessionContext;
import javax.ejb.Stateless;
@Stateless
@DeclareRoles({"Usuarios"})
public class EjemploSeguridadBean implements EjemploSeguridadBeanRemote {
@Resource
SessionContext ctx;
@RolesAllowed(value = {"Usuarios"})
public String probarSeguridadEJB() {
return "El nombre de usuario desde EJB es:" + ctx.getCallerPrincipal().getName();
}
}


Luego de esto, regresamos al proyecto web y cambiamos el servlet Cliente.java al siguiente código:

Cliente.java

De la misma manera que en el Bean, por medio de las anotaciones @DeclareRoles({"Usuarios"})
y
@ServletSecurity(@HttpConstraint(rolesAllowed={"Usuarios"}))
podemos definir que usuarios pueden ejecutar estas rutinas

package com.web;

import com.ejb.EjemploSeguridadBeanRemote;
import java.io.IOException;
import java.io.PrintWriter;
import javax.annotation.security.DeclareRoles;
import javax.ejb.EJB;
import javax.servlet.ServletException;
import javax.servlet.annotation.HttpConstraint;
import javax.servlet.annotation.ServletSecurity;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet(name="Cliente", urlPatterns={"/Cliente"})
@DeclareRoles({"Usuarios"})
@ServletSecurity(@HttpConstraint(rolesAllowed={"Usuarios"}))
public class Cliente extends HttpServlet {
@EJB private EjemploSeguridadBeanRemote bean;

protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
try {
out.println("<html>");
out.println("<head>");
out.println("<title>Servlet Cliente1</title>");
out.println("</head>");
out.println("<body>");
out.println("<h1>Informacion de Seguridad Desde WEB</h1>");
out.println("Usuario: " + request.getUserPrincipal().getName()+"<br/>");
out.println("Tipo de Autenticacion: " + request.getAuthType()+"<br/>");
out.println("Nombre Servidor: " + request.getServerName()+"<br/>");
out.println("<h1>Informacion de Seguridad Desde EJB</h1>");
out.println(bean.probarSeguridadEJB());
out.println("</body>");
out.println("</html>");

} finally {
out.close();
}

}
....


Con lo cual tenemos:

Si nos equivocamos en el usuario o clave, nos saldrá el siguiente mensaje:
Si ingresamos con usuario y la clave que definimos en Glassfish.

Se nos muestran las siguientes opciones:
Si damos click en datos informativos tenemos:
y al dar click en logout:

1 comentario: