When using jdbcRealm
, it is good to use security managed by the container , i.e., container-managed-security
for authentication and authorization of resources in your app. instead of manipulating it from the code itself, although depending on the requirements, it may be necessary and there is another way to delegate the "login" to the application server.
The server is the one who will be responsible for authenticating and authorizing users depending on their role in the application. and to activate the servlet that handles this process, you have to create a html form according to Servlet specification :
the form should go on a separate page that usually only contains the form to login:
Then in the Descriptor de Despliegue
(web.xml) we must add the configuration that will tell the server:
- what are the resources (pages, folders) that will be restricted
depending on the role of the user
- We establish the existant roles
- We set the route of the login page
- We establish information protection (SSL)
web.xml :
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.1"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
<security-constraint>
<display-name>Restricción 1</display-name>
<web-resource-collection>
<web-resource-name>resources</web-resource-name>
<description />
<url-pattern>/protected/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>appUser</role-name>
<role-name>appAdmin</role-name>
</auth-constraint>
</security-constraint>
<login-config>
<auth-method>FORM</auth-method>
<realm-name>appRealm</realm-name>
<form-login-config>
<form-login-page>/index.xhtml</form-login-page>
<form-error-page>/public/forbidden.xhtml</form-error-page>
</form-login-config>
</login-config>
<security-role>
<role-name>appUser</role-name>
</security-role>
<security-role>
<role-name>appAdmin</role-name>
</security-role>
<error-page>
<error-code>403</error-code>
<location>/public/forbidden.xhtml</location>
</error-page>
</web-app>
Now we have to map the roles with the groups in the database and this depends a lot on the Server that is being used, for this example I do it with Glassfish
we create a file glassfish-web.xml
or sun-web.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sun-web-app PUBLIC "-//Sun Microsystems, Inc.//DTD GlassFish Application Server 3.0 Servlet 3.0//EN" "http://www.sun.com/software/appserver/dtds/sun-web-app_3_0-0.dtd">
<sun-web-app error-url="">
<security-role-mapping>
<role-name>appUser</role-name>
<group-name>1</group-name>
</security-role-mapping>
<security-role-mapping>
<role-name>appAdmin</role-name>
<group-name>2</group-name>
</security-role-mapping>
<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>
</sun-web-app>
Now we create the database that will contain the info for this to work:
CREATE TABLE 'tabla_usuarios'(
correo VARCHAR(255),
pwd VARCHAR(255) NOT NULL,
PRIMARY KEY (correo)
)ENGINE=INNODB DEFAULT CHARACTER SET UTF8;
CREATE TABLE grupos(
correo VARCHAR(255),
grupo VARCHAR(30),
PRIMARY KEY(correo)
)ENGINE=INNODB DEFAULT CHARACTER SET UTF8;
These would be the minimum requirements for the DB.
The only thing missing now is to create the realm
(realm) on the server.
We open the administration console, localhost:4848
and go to:
Configurations >> Server-Config >> Security >> Realms
We create a new realm:
The name must be the same as the one set in realm-name
We select from select
the option that jdbcRealm has
Then we fill in the boxes with the corresponding information:
- JAAS Context = jdbcRealm
- JNDI = jndi_name (in glassfish-resources.xml is found)
- User Table = user_table
- User Name Column = user_table.mail
- Password Column = user_table.pwd
- Group Table = groups
- Group Table User Name Column = groups.mail
- Group Name Column = groups.group
- Password Encryption Algorithm = SHA-256
- Datablase User = user_to_accesso_a_db
- Database Password = db_user_password
The rest of the boxes can be left blank but you have to have one thing in mind, from Glassfish 4.+
this forces us to use an algorithm to encrypt the passwords, so I have put SHA-256
now to save users you have to save your passwords in SHA-256
at the time you register them so that JAAS
works.
To encrypt:
public static String encriptar(String contrasena) throws NoSuchAlgorithmException{
byte[] bytes = MessageDigest.getInstance("SHA-256").digest(contrasena.getBytes());
return DatatypeConverter.printHexBinary(bytes).toLowerCase();
}