2. CONTENIDOS
Introducción.
Criptografía con Java.
Infraestructura con PKI con Java.
Control de acceso.
Aplicaciones con Java SSL.
Seguridad en aplicaciones WEB.
Introducción a la seguridad en los web services.
3. Control de acceso
Evolución del modelo de seguridad.
El “Security Manager”.
Evolución del “Security Manager”.
Cómo portar gestores de seguridad de la 1.1.
Ficheros de políticas de seguridad (Policy Files).
Cambios en las políticas en Java 2 SDK SE 1.4.
Implementación por defecto de políticas de seguridad.
Localizaciones por defecto de los ficheros de políticas.
Especificar un fichero de políticas adicional en tiempo
de ejecución.
Cambiar la implementación de Policy.
4. Control de acceso
Sintaxis del fichero de políticas.
Ejemplos de ficheros de políticas de seguridad.
Expansión de propiedades en los ficheros de políticas.
Java Authentication and Authorization Service
(JAAS).
Introducción.
Descripción del servicio JAAS.
Autenticación JAAS.
Autorización JAAS.
Conclusión.
5. Control de acceso
Java proporciona en sus API un conjunto de
clases, interfaces y herramientas que
proporcionan la seguridad para las aplicaciones.
El desarrollador J2EE tiene que tener una
comprensión profunda de los fundamentos de la
seguridad Java.
Sin embargo, no tiene que saber cómo se
implementan las medidas de seguridad.
6. Evolución del modelo de seguridad
JDK 1.1: las aplicaciones locales y applets
firmados digitalmente de forma correcta tenían
acceso total a recursos vitales del sistema,
como el sistema de archivos, mientras que los
applets sin firma podían acceder sólo a recursos
limitados. Un “security manager” era
responsable de determinar qué accesos a
recursos se permitían.
Java 2 SDK: basada en políticas de seguridad
(policies). La política de seguridad especifica
qué permisos están disponibles para el código.
7. Métodos del Security Manager
La clase SecurityManager contiene varios
métodos con nombres que comienzan por la
palabra check:
checkRead
checkConnect
…
Muchos métodos de las bibliotecas de Java
llaman a un método check antes de realizar una
operación sensible a la seguridad. De este
modo se le da una oportunidad al security
manager de prevenir la ejecución de la
operación lanzando una excepción.
8. Métodos del Security Manager
Una rutina del gestor de seguridad simplemente
retorna si la operación está permitida, pero
lanza una excepción si la operación no lo está.
Existe otro tipo de métodos contenidos en la
clase SecurityManager, relacionados con la
existencia y profundidad del class loader:
currentClassLoader
currentLoadedClass
inClassLoader
classLoaderDepth
9. Security Manager en JDK 1.1
Cualquier aplicación que quería instalar un
gestor de seguridad tenía que escribirlo ella
misma, proporcionando implementaciones
concretas apropiadas de los métodos que
lanzaban excepciones por defecto, sobre todo
los métodos check.
La clase java.lang.SecurityManager era
abstracta.
10. Security Manager en JDK 1.1
Las decisiones sobre control de acceso se
basaban en:
si una clase con un class loader (por ejemplo, un
applet en JDK 1.1) estaba en la pila o no.
la profundidad del class loader (cómo de profunda en
la pila estaba la ocurrencia más reciente de un método
de una clase definida usando un class loader).
11. Security Manager en JDK 1.1
Ejemplo de método check de un
SecurityManager. No permite la llamada a
Runtime.exit cuando haya en la pila una clase
definida con un class loader:
public void checkExit(int status) {
if (inClassLoader()) {
throw new SecurityException(…);
}
}
12. Security Manager en JDK 1.1
Ejemplo de método check de un
SecurityManager. No permite la creación de un
class loader cuando la profundidad del propio
sea 2:
public void checkCreateClassLoader() {
if (ClassLoaderDepth()==2) {
throw new SecurityException(…);
}
}
13. Security Manager en Java 2 SDK
Cambios en java.lang.SecurityManager:
Ya no es una clase abstracta.
La mayoría de los métodos check llaman a un nuevo
método checkPermission, que por defecto llama al
método del mismo nombre (checkPermission) en la
nueva clase AccessController.
Los métodos usados en JDK 1.1 para determinar si
una clase está en la pila o para calcular la profundidad
del cargador de clases han sido modificados en el Java
2 SDK para ignorar los cargadores de clases del
sistema y contextos de seguridad que ha sido
garantizados por java.security.AllPermission.
14. Security Manager en Java 2 SDK
Como SecurityManager ya no es una clase
abstracta, ahora se puede instanciar y usar
directamente como gestor de seguridad por
defecto. Esto se puede hacer:
Estableciendo la propiedad del sistema adecuada
conforme se lanza la VM:
java –Djava.security.manager TuAplicacion
Vía código:
System.setSecurityManager(new SecurityManager());
Su comportamiento se podrá modificar
mediante ficheros de políticas de seguridad
(policy files).
15. Security Manager en Java 2 SDK
Ejemplo:
public class PropiedadesSistema {
public static void main(String[] args) {
System.out.println(System.getProperty("java.version"));
System.out.println(System.getProperty("java.home"));
System.out.println(System.getProperty("java.vendor"));
}
}
Analizar la salida.
16. Políticas de seguridad
La política de seguridad para un entorno de
aplicación en lenguaje Java está asociado a un
objeto Policy.
Se representa mediante una subclase de
Policy, que proporciona una implementación
de los métodos abstractos de la clase Policy
(en el paquete java.security).
Esta implementación viene indicada en el
fichero java.security .
18. Políticas de seguridad
Con la integración del servicio JAAS en el J2SDK
1.4, la API java.security.Policy maneja
consultas basadas en Principal.
La implementación por defecto de las políticas
de seguridad soportan entradas grant
(garantías de permiso) basadas también en
principales.
El control de acceso puede ahora basarse no
sólo en qué código se está ejecutando, sino
también en quién lo está ejecutando.
19. Implementación por defecto de las políticas de
seguridad
Las políticas se establecen en uno o más
ficheros de políticas de seguridad (Policy File),
que detallan qué permisos se conceden al
código en función de qué código es, de que
fuente viene y quién lo está ejecutando.
Un fichero de políticas está codificado UTF-8 y
se puede crear con un simple editor de texto o
la herramienta gráfica Policy Tool.
Por defecto hay un único fichero global al
sistema y otro opcional para el usuario.
20. Localización por defecto de los ficheros de
políticas
El fichero de políticas de seguridad del sistema
se localiza por defecto en:
java.home/lib/security/java.policy (Solaris)
java.homelibsecurityjava.policy (Win32)
La propiedad del sistema “java.home” especifica
el directorio de instalación del SDK.
El fichero de políticas del usuario se localiza por
defecto en:
user.home/.java.policy (Solaris)
user.home.java.policy (Win32)
22. Localización por defecto de los ficheros de
políticas
El fichero de políticas instalado por defecto con
el SDK permite a cualquier:
Escuchar en un puerto no privilegiado
Permite a cualquier código leer propiedades
“estándar” que no sean sensibles a la seguridad.
23. Policy files
El funcionamiento del sistema de políticas de
seguridad es: primero se carga el fichero de
políticas del sistema y, posteriormente, se
añade el/los de usuario.
Las localizaciones de los ficheros de políticas de
seguridad están detalladas en el fichero de
propiedades de seguridad, que se encuentra en:
java.home/lib/security/java.security (Solaris)
java.homelibsecurityjava.security (Win32)
24. Policy files
Las localizaciones de los ficheros de políticas
están especificadas como valores de las
propiedades que tienen la siguiente forma:
policy.url.n =URL (n es un número, que actúa como
contador del número de ficheros de políticas).
Ejemplo:
policy.url.1=file:${java.home}/lib/security/java.policy
policy.url.2=file:${user.home}/.java.policy
Se cargarán sólo los ficheros indicados con
índices consecutivos. Si hay un hueco en los
números no se cargarán los ficheros a partir del
hueco.
27. Policy files
Se puede especificar un fichero de políticas
adicional en tiempo de ejecución:
java –Djava.security.manager –
Djava.security.policy=unaURL MiApp
Ese ejemplo cargaría el fichero especificado por
unaURL además de los especificados en las
propiedades de seguridad. Si se usase un ‘==‘
en lugar de un ‘=‘ entonces sólo se cargaría el
fichero de políticas especificado.
28. Cambio de implementación
Se puede proporcionar una clase de políticas
alternativa para reemplazar la implementación
de referencia de la clase Policy.
Una subclase de Policy.
Implementación de todos los métodos necesarios.
La implementación de referencia puede ser
cambiada editando el fichero java.security
cambiando la propiedad:
policy.provider = NombreClase
29. Sintaxis del fichero de políticas
Los ficheros de configuración de políticas de
seguridad especifican qué permisos (qué tipos
de accesos a recursos del sistema) se
garantizan al código de una fuente concreta de
código y ejecutado por un determinado
principal.
Un policy file contiene:
Una entrada keystore (opcional).
Cero o más entradas grant.
30. Sintaxis del fichero de políticas
La entrada keystore: sirve para definir el
keystore usado para buscar las claves públicas
de los firmantes especificados en las entradas
grant del fichero.
Si alguna entrada grant especifica alias de
firmantes o principales entonces debe aparecer
una entrada keystore.
Sólo puede haber una entrada keystore en el
fichero de políticas de seguridad. Si se ponen
más de una, sólo se considerará la primera.
Puede aparecer en cualquier lugar del fichero.
31. Sintaxis del fichero de políticas
Sintaxis de la entrada keystore:
keystore "ks_url", "ks_tipo", "ks_proveedor";
keystorePasswordURL "password_url";
Las URLs indicadas son relativas con respecto al
directorio donde se encuentra el fichero de
políticas en cuestión.
Tipo de keystore: define el formato de los datos
y su almacenamiento y los algoritmos usados
para protegerlo. El tipo por defecto soportado
por Sun es un tipo propietario llamado “JKS”.
32. Sintaxis del fichero de políticas
Entradas grant: especifica qué permisos se
conceden a qué código. El formato básico es:
grant signedBy "signer_names", codeBase "URL",
principal principal_class_name "principal_name",
principal principal_class_name "principal_name",
... {
permission permission_class_name "target_name", "action",
signedBy "signer_names";
permission permission_class_name "target_name", "action",
signedBy "signer_names";
...
};
33. Sintaxis del fichero de políticas
Un código en ejecución siempre viene de una
fuente (code source) concreta, representada
por un objeto CodeSource y que se está
ejecutando como un principal concreto,
representado por un objeto Principal.
El code source incluye la URL donde se originó
el código y, además, una referencia a los
certificados que contienen las claves públicas
correspondientes a las claves privadas usadas
para firmar dicho código:
codeBase
signedBy
34. Sintaxis del fichero de políticas
Los campos signedBy, principal y codeBase son
opcionales y no importa el orden entre ellos.
signedBy: referencia un alias de un certificado
que está almacenado en el keystore. Una
entrada con signedBy está concediendo
permisos al código firmado con la clave privada
correspondiente a la clave pública almacenada
en la entrada del keystore indicada por el alias.
Su valor puede ser una lista de múltiples alias,
indicando que el código está firmado por todos
ellos (operación AND).
35. Sintaxis del fichero de políticas
principal: especifica un par nombre de clase/
nombre de principal.
Nota: si se especifica el valor del principal
como una cadena de texto entre comillas (sólo
se está dando el nombre de principal, en lugar
del par), se trata como una alias del keystore.
Si no se encuentra en el keystore el certificado
correspondiente a ese alias, se ignora la
entrada grant entera. Si se encuentra, se
considera que el nombre de la clase es
“javax.security.auth.x500.X500Principal”
y la cadena el nombre distinguido del principal.
36. Sintaxis del fichero de políticas
Ejemplo:
grant
Principal com.sun.security.auth.SolarisPrincipal "duke",
Principal com.sun.security.auth.SolarisNumericUserPrincipal "0" {
permission java.io.FilePermission "/home/duke", "read, write";
permission java.net.SocketPermission "duke.com", "connect";
};
Se está garantizando permisos de lectura y
escritura a ficheros del directorio home del
usuario “duke” y de creación de sockets a
“duke.com” a cualquier código ejecutándose
como “duke” o “0”.
37. Sintaxis del fichero de políticas
Las entradas de permisos: deben
empezar por la palabra permission. Los
permisos corresponden a clases
específicas de Java.
Para muchos permisos se requiere una
acción, por ejemplo, para
FilePermission, que indique que tipo
de acceso a ficheros es el que se está
permitiendo.
38. Sintaxis del fichero de políticas
Las entradas permission tienen una claúsula
signedBy opcional, que indica que la clase
correspondiente al permiso debe estar firmada
por el alias indicado.
Ejemplo: se concede un permiso de tipo Foo si
la clase Foo.class se encuentra en un JAR que
has sido firmado por “FooSoft”.
grant {
permission Foo “foobar”, signedBy “FooSoft”;
};
39. Sintaxis del fichero de políticas
Las clases de sistema no están sujetas a
las restricciones de las políticas de
seguridad, por lo que si, en el ejemplo
anterior, Foo.class fuera una clase de sistema,
entonces ese permiso estaría implícito.
Las entradas permission termina con ‘;’.
En las palabras reservadas de los ficheros de
políticas no se distinguen mayúsculas y
minúsculas.
40. Sintaxis del fichero de políticas
Tipos de permisos incorporados por JDK
(consultar las API):
java.security.AllPermission
java.security.SecurityPermission
java.security.UnresolvedPermission
java.awt.AWTPermission
java.io.FilePermission
java.io.SerializablePermission
java.lang.reflect.ReflectPermission
java.lang.RuntimePermission
java.net.NetPermission
41. Sintaxis del fichero de políticas
java.net.SocketPermission
java.sql.SQLPermission
java.util.PropertyPermission
java.util.logging.LoggingPermission
javax.net.ssl.SSLPermission
javax.security.auth.AuthPermission
javax.security.auth.PrivateCredentialPermission
javax.security.auth.kerberos.DelegationPermission
javax.security.auth.kerberos.ServicePermission
javax.sound.sampled.AudioPermission
42. Ejemplos de Policy Files
grant signedBy "Duke" {
permission java.io.FilePermission "/tmp/*", "read,write";
};
grant {
permission java.util.PropertyPermission "java.vendor", "read";
};
grant signedBy "sysadmin", codeBase "file:/home/sysadmin/*" {
permission java.security.SecurityPermission "Security.insertProvider.*";
permission java.security.SecurityPermission "Security.removeProvider.*";
permission java.security.SecurityPermission "Security.setProperty.*";
};
grant principal javax.security.auth.x500.X500Principal "cn=Alice" {
permission java.io.FilePermission "/home/Alice", "read, write";
};
grant codebase "http://www.games.com",
signedBy "Duke",
principal javax.security.auth.x500.X500Principal "cn=Alice" {
permission java.io.FilePermission "/tmp/games", "read, write";
};
43. Especificación de rutas de archivos en Win32
Cuando se está concediendo un
FilePermission, el “target_name” es una ruta
de archivo. En sistemas Win32, si se especifica
directamente una ruta en una cadena, es
necesario incluir dos barras () por cada una
que aparezca en la ruta, así:
grant {
permission java.io.FilePermission "C:userscathyfoo.bat", "read";
};
44. Expansión de propiedades
La expansión de propiedades es posible tanto
en los ficheros de políticas de seguridad como
en los ficheros de propiedades de seguridad.
La expansión de propiedades es similar a la
expansión de variables en una shell. Así,
cuando una cadena como “${propiedad}”
aparece en un fichero de políticas o en uno de
propiedades de seguridad, será expandido al
valor de la propiedad correspondiente del
sistema.
45. Expansión de propiedades
Ejemplo:
permission java.io.FilePermission "${user.home}", "read";
Si la propiedad “user.home” del sistema vale “/
home/cathy” se expandirá a:
permission java.io.FilePermission "/home/cathy", "read";
Para ayudar a la creación de ficheros de
políticas independientes de la plataforma,
también se puede usar la notación especial “$
{/}”, que es una referencia corta a “$
{file.separator}” (propiedad del sistema que
indica cuál es el separador usado en las rutas,
‘’ en Win32, ‘/’ en Unix, por ejemplo).
46. Expansión de propiedades
Ejemplo:
permission java.io.FilePermission "${user.home}${/}*", "read”;
Si la propiedad “user.home” del sistema vale “/home/
cathy” se expandirá a:
permission java.io.FilePermission "/home/cathy/*", "read";
No se pueden anidar las propiedades para su expansión.
Estaría MAL:
“${user.${foo}}”
Si una propiedad dentro de una entrada grant,
permission o keystore no se puede expandir, se ignora la
entrada entera.
47. Servicio de autenticación y autorización
Introducción.
Autenticación JAAS.
Ejemplo JAAS.
Autorización JAAS.
47
48. Introducción
JAAS aumenta los controles de acceso basados
en código existentes anteriormente con
controles de acceso basado en el usuario y
capacidades de autenticación.
Esto permite garantizar permisos basados no
sólo en qué código se está ejecutando, sino
también en quién lo está ejecutando.
49. Introducción
JAAS consiste en dos partes: la autenticación y
la autorización. Esto quiere decir que se puede
usar tanto para la autenticación como para la
autorización:
Para la autenticación de usuarios y así determinar de
forma segura quién está ejecutando código Java, sin
tener en cuenta si el código es una aplicación Java
independiente, un applet, un EJB o un servlet.
Para la autorización de usuarios y garantizar que
tienen los permisos requeridos para realizar las
acciones.
50. Introducción
La autenticación está basada en los Pluggable
Authentication Modules (PAMs) con un
framework que se usará tanto para clientes
como para servidores.
La realización de la autenticación usando PAMs
permite a las aplicaciones Java ser
independientes del mecanismo de autenticación
subyacente.
Esto tiene la ventaja de que nuevos o revisados
mecanismos de autenticación podrán ser
incorporados sin modificar la aplicación en sí
misma.
51. Introducción
La autorización es una extensión del mecanismo
existente basado en ficheros de políticas que se
usa para especificar qué se le permite a una
aplicación hacer o no hacer.
Está basada en dominios de protección.
Anteriormente, este mecanismo garantiza
permisos en función de dónde viene el código y
no en quién lo está ejecutando.
Con JAAS, los permisos y el control de acceso
se pueden basar no sólo en qué código se está
ejecutando sino también en quién lo está
haciendo, como ya se ha visto.
52. Introducción
Los paquetes siguientes componen la
arquitectura JAAS:
javax.security.auth: contiene clases básicas para la
autenticación y autorización.
javax.security.auth.callback: contiene una estructura
de clases e interfaces para envío de información de
autenticación a la aplicación.
java.security.auth.login: contiene clases que emplean
para conectarse a un dominio de seguridad.
javax.security.auth.spi.
53. Autenticación JAAS
Sujeto: identidad en un sistema que se quiere
autenticar y a la que se le quieren asignar
derechos de acceso.
Un sujeto puede ser un usuario humano, un
proceso o una máquina y está representado por
la clase javax.security.auth.Subject.
Analizar la clase en las APIs de Java.
54. Autenticación JAAS
Un sujeto puede interactuar con múltiples
autoridades (una clave para una web bancaria,
otra para una cuenta de correo, otra para una
intranet…)
Por esa razón, se usa
java.security.Principal para representar la
identidad en esas interacciones.
Ver APIs de Java.
55. Autenticación JAAS
La interfaz Principal es una noción abstracta
que puede ser usada para representar una
entidad, una empresa o una ID de usuario. Un
Subject puede contener múltiples principales.
Contexto de conexión (LoginContext): objeto a
través del que los clientes interactúan con
JAAS.
Módulo de conexión (LoginModule):
responsable de implementar y realizar la
autenticación. Será implementado por diversos
proveedores de tecnología de autenticación.
56. Autenticación JAAS
Los elementos que integran el sistema son:
Contexto de login (LoginContext).
Configuración específica.
Módulos de login (LoginModule).
CallBackHandler.
57. Autenticación JAAS
Contexto de login:
Funcionamiento general: el objeto LoginContext lee
la configuración e instancia el LoginModule
especificado.
Normalmente se usarán módulos de conexión ya
desarrollados y no deberemos codificar ninguno.
Sun Microsystems pone a nuestra disposición varios:
JndiLoginModule
KeyStoreLoginModule
Krb5LoginModule
NTLoginModule
UNIXLoginModule
58. Autenticación JAAS
Contexto de login:
La cadena de módulos que va a ser aplicada se indica
a la hora de crear el objeto contexto mediante su
constructor.
public LoginContext()
Ver la API de Java.
La configuración se indica mediante un fichero
de configuración.
59. Autenticación JAAS
Configuración:
Especifica la tecnología de autenticación, o
LoginModule usado.
Así se puede cambiar el LoginModule usado sin que
sea necesario ningún cambio en el código de la
aplicación.
Se apoya en la clase abstracta Configuration del
paquete javax.security.auth.login.
Application {
ModuleClass Flag ModuleOptions;
ModuleClass Flag ModuleOptions;
ModuleClass Flag ModuleOptions;
};
Mirar APIs de Java.
60. Autenticación JAAS
Configuración (cont.):
ModuleClass: nombre de la clase.
Flag:
Required.
Requisite.
Sufficient.
Optional.
Login {
com.sun.security.auth.module.UnixLoginModule required;
com.sun.security.auth.module.Krb5LoginModule optional;
};
61. Autenticación JAAS
Configuración (cont.):
Required:
El módulo de conexión asociado debe ser capaz de
autenticar el sujeto en todo el proceso de autenticación
para poder éxito. Independientemente de que falle o no,
se continua en la cadena de módulos hasta el final.
Requisite:
El módulo de conexión asociado debe tener éxito para
que se considere que todo el proceso de autenticación ha
tenido éxito. Si el módulo falla, el proceso de
autenticación no continua. Devuelve el control a la
aplicación.
62. Autenticación JAAS
Configuración (cont.):
Sufficient:
No es requisito indispensable para la autenticación. Ahora
bien, si el módulo se supera con éxito la autenticación es
automática.
Optional: no es necesaria la capacidad que tiene el
módulo de conexión asociado para autenticar al
sujeto. El proceso de autenticación sigue por la lista
buscando otros módulos de conexión.
64. Autenticación JAAS
Módulo de login:
Si se implementa un LoginModule se debe dar cuerpo
a los siguientes métodos (LoginContext los usará en
ese orden):
initialize: el propósito de este método es inicializar
este LoginModule con la información relevante. El
Subject pasado a este método se usa para almacenar los
principales (Principal) y credenciales (Credential) si la
conexión tiene éxito. Nótese que este método recibe un
CallbackHandler que puede ser usado para introducir
información de la autenticación.
65. Autenticación JAAS
Módulo de login:
login: le pide al LoginModule que autentique al
Subject. Nótese que el Principal todavía no ha sido
asignado.
commit: se llama a este médodo si tiene éxito la
autenticación total del LoginContext.
abort: informa al LoginModule de que algún
proveedor o módulo ha fallado al autenticar al
Subject. En ese caso la conexión entera (el logado)
debe fracasar.
logout: desconecta al Subject borrando los
principales (Principal) y credenciales (Credential)
del Subject.
66. Ejemplo JAAS: WeatherLoginModule.java
import java.io.*;
import java.util.*;
import java.security.Principal;
import javax.security.auth.Subject;
import javax.security.auth.callback.*;
import javax.security.auth.spi.LoginModule;
import javax.security.auth.login.LoginException;
public class WeatherLoginModule implements LoginModule {
private Subject subject;
private ExamplePrincipal entity;
private CallbackHandler callbackhandler;
private static final int NOT = 0;
private static final int OK = 1;
private static final int COMMIT = 2;
private int status;
public void initialize(Subject subject, CallbackHandler//
callbackhandler, Map state, Map options) {
status = NOT;
entity = null;
this.subject = subject;
this.callbackhandler = callbackhandler;
}
67. Ejemplo JAAS: WeatherLoginModule.java
public boolean login() throws LoginException {
if(callbackhandler == null) {
throw new LoginException("No callback handler is available");
}
Callback callbacks[] = new Callback[1];
callbacks[0] = new NameCallback("What is the weather like today?");
String name = null;
try {
callbackhandler.handle(callbacks);
name = ((NameCallback)callbacks[0]).getName();
} catch(java.io.IOException ioe) {
throw new LoginException(ioe.toString());
} catch(UnsupportedCallbackException ce) {
throw new LoginException("Error: "+ce.getCallback().toString());
}
if(name.equals("Sunny")) {
entity = new ExamplePrincipal("SunnyDay");
status = OK;
return true;
} else {
return false;
}
}
70. Autenticación JAAS
CallbackHandler:
Una aplicación basada en JAAS implementa la interfaz
CallbackHandler de forma que pueda interactuar con
los usuarios para introducir los datos específicos de
autenticación, tales como usuario y clave, o mostrar
mensajes de error y advertencia.
Implementar la interfaz significa darle cuerpo al
método handle para recuperar o mostrar la
información requerida en las llamadas.
71. Autenticación JAAS
CallbackHandler:
Diferentes tipos de respuesta:
NameCallback: pasa al método handle de
CallbackHandler una respuesta al nombre de
autenticación.
PasswordCallback.
ChoiceCallback: muestra una lista de opciones y
captura la elegida por el usuario.
ConfirmationCallback: pregunta por YES/NO, OK/
CANCEL, YES/NO/CANCEL u otras confirmaciones
similares.
72. Autenticación JAAS
TextInputCallback: recupera información genérica de
texto.
TextOutputCallback: muestra información o mensajes de
error o advertencia.
Otras clases que implementan la interfaz Callback…
73. Ejemplo JAAS: MyCallbackHandler.java
import javax.security.auth.Subject;
import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;
public class MyCallbackHandler implements CallbackHandler {
public void handle(Callback callbacks[]) throws IOException,
UnsupportedCallbackException {
for(int i=0;i<callbacks.length;i++) {
if(callbacks[i] instanceof NameCallback) {
NameCallback nc = (NameCallback) callbacks[0];
System.err.print(nc.getPrompt());
System.err.flush();
String name = (new BufferedReader(
new InputStreamReader(System.in))).readLine();
nc.setName(name);
} else {
throw(new UnsupportedCallbackException(callbacks[i],
"Callback handler not support"));
}
}
}
}
74. Ejemplo JAAS: ExamplePrincipal.java
Esta clase es una implementación de
Principal, a la que se ha hecho referencia en
nuestro LoginModule:
import java.security.Principal;
public class ExamplePrincipal implements Principal {
private final String name;
public ExamplePrincipal(String name) {
if(name == null) {
throw new IllegalArgumentException("Null name");
}
this.name = name;
}
…
…
75. Ejemplo JAAS: ExamplePrincipal.java
…
…
public String getName() {
return name;
}
public String toString() {
return "ExamplePrincipal: "+name;
}
public boolean equals(Object obj) {
if(obj == null) return false;
if(obj == this) return true;
if(!(obj instanceof ExamplePrincipal)) return false;
ExamplePrincipal another = (ExamplePrincipal) obj;
return name.equals(another.getName());
}
public int hasCode() {
return name.hashCode();
}
}
76. Ejemplo JAAS: example.conf
Fichero de configuración. La entrada del fichero
debe ser la misma que se usa en el cliente.
Especifica el módulo que se va a usar para la
autenticación.
WeatherLogin {
WeatherLoginModule required;
};
77. Ejecución del ejemplo JAAS
Crear un directorio.
Copiar MyClient.java,
WeatherLoginModule.java,
ExamplePrincipal.java y example.conf a ese
directorio.
Compilar todos los fichero .java:
javac *.java
Ejecutar el cliente usando el siguiente comando,
que especifica el fichero de configuración de
conexión:
java –Djava.security.auth.login.config=example.conf
MyClient
78. Autorización JAAS
La autorización JAAS extiende la arquitectura de
seguridad de Java centrada en el código que
usa políticas de seguridad para especificar qué
derechos de acceso están garantizados para un
código en ejecución.
Los permisos se pueden garantizar no sólo en
función de qué código se está ejecutando, sino
además, quién lo está ejecutando.
Los permisos se pueden garantizar en el fichero
de políticas para especificar principales.
79. Autorización JAAS
Importante:
Para la autorización primero se debe haber procedido
a la autenticación del usuario.
Hay que llamar al método doAs (o doAsPrivileged)
de la clase Subject, que invocará el método run que
contiene el código a ser ejecutado como el sujeto
especificado.
80. Ejemplo de Autorización JAAS
Vamos a ampliar el ejemplo usado en
autenticación JAAS para que trabaje también
con autorización.
Los ficheros ExamplePrincipal.java,
WeatherLoginModule.java y example.conf no
sufren ninguna modificación.
El objetivo del ejemplo es que el código habilite
autorice a un usuario que se ha autenticado a
realizar una acción.
81. Ejemplo de Autorización JAAS
MyClient.java: ahora, una vez que la
autenticación tenga éxito, deberá realizar lo
siguiente:
Subject subject = ctx.getSubject();
PrivilegedAction action = new MyAction();
Subject.doAsPrivileged(subject, action, null);
try {
ctx.logout();
} catch(LoginException le) {
System.out.println("Logout: " + le.getMessage());
}
Se hace que el sujeto realice una acción (definida en
la clase MyAction) como el sujeto autenticado.
82. Ejemplo de Autorización JAAS
MyAction.java:
import java.io.File;
import java.security.PrivilegedAction;
public class MyAction implements PrivilegedAction {
public Object run() {
File file = new File("max.txt");
if(file.exists()) {
System.out.println("The file exists in the current
working directory");
} else {
System.out.println("The file does not exist in the
current working directory");
}
return null;
}