Monday 21 November 2011

EJB Security configuration in Glassfish 3.1

Assume the MySQL data source has been set up. (If not, check Configure MySQL datasource in Glassfish 3.1)

The JNDI name is jdbc/mysql

Start Glassfish, go to Admin Console, http://localhost:4848

Configurations -> server-config -> Security -> Realms


Click on 'New' button

Name: jdbcRealm
Class Name: Select com.sun.enterprise.security.auth.realm.jdbc.JDBCRealm
JAAS Context: jdbcRealm
JNDI: jdbc/mysql
User Table: T_USER
User Name Column: username
Password Column: password
Group Table: T_GROUP
Group Name Column: groupname
Digest Algorithm: none


 

In the MySQL data source, create two tables: T_USER and T_GROUP

CREATE TABLE T_USER (
  `username` VARCHAR(30) NOT NULL,
  `password` VARCHAR(30) NOT NULL,
  PRIMARY KEY (`username`)
)

CREATE TABLE T_GROUP (
  `username` VARCHAR(30) NOT NULL,
  `groupname` VARCHAR(30) NOT NULL,
  PRIMARY KEY (`username`)
)

Insert data

insert into T_USER values (‘sun’, ‘123’);
insert into T_USER values (‘ming’, ‘456’);
insert into T_GROUP values (‘sun’, ‘adminGroup’);
insert into T_GROUP values (‘ming’, ‘userGroup’);

Create a stateless session bean

@Stateless(name="securityManager")
@Local(SecurityManager.class)

public class SecurityManagerBean implements SecurityManager {

    @Resource
    private EJBContext context;
    
    @RolesAllowed({"admin"})
    public void save() {
        System.out.println("User: "
                +context.getCallerPrincipal().getName());
        System.out.println("Save");
    }

}

Create a servlet

public class SecurityServlet extends HttpServlet {

    @EJB(beanName="securityManager")
    private SecurityManager securityManager;
    
    @Override
    protected void doGet(HttpServletRequest req, 
            HttpServletResponse resp)
            throws ServletException, IOException {
        securityManager.save();
    }
}

Edit web.xml under WEB-INF

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 
    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_2_5.xsd">
    <security-role>
        <role-name>user</role-name>
    </security-role>
    
    <security-role>
        <role-name>admin</role-name>
    </security-role>
    
    <security-constraint>
        <web-resource-collection>
            <web-resource-name>all resources</web-resource-name>
            <url-pattern>/se</url-pattern>
            <http-method>GET</http-method>
            <http-method>POST</http-method>
            <http-method>HEAD</http-method>
        </web-resource-collection>
        <auth-constraint>
            <role-name>user</role-name>
            <role-name>admin</role-name>
        </auth-constraint>
        <user-data-constraint>
            <transport-guarantee>NONE</transport-guarantee>
        </user-data-constraint>
    </security-constraint>
    
    <login-config>
        <auth-method>BASIC</auth-method>
           <realm-name>jdbcRealm</realm-name>
    </login-config>

    <servlet>
        <servlet-name>se</servlet-name>
        <servlet-class>web.SecurityServlet</servlet-class>
    </servlet>
    
    <servlet-mapping>
        <servlet-name>se</servlet-name>
        <url-pattern>/se</url-pattern>
    </servlet-mapping>
</web-app> 

Note: The value of <realm-name> (jdbcRealm) must match the Name field in Admin Console.


Edit sun-web.xml under WEB-INF

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE sun-web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Application Server 8.1
Servlet 2.5//EN" "http://www.sun.com/software/appserver/dtds/sun-web-app_2_5-0.dtd">

<sun-web-app>
    <security-role-mapping>
       <role-name>user</role-name>
       <group-name>userGroup</group-name>
    </security-role-mapping>

    <security-role-mapping>
       <role-name>admin</role-name>
       <group-name>adminGroup</group-name>
    </security-role-mapping>
</sun-web-app>


Note: The value of <role-name> must match the value of <role-name> under <security-role> in web.xml. The value of <group-name> must match the value of groupname column in T_GROUP table.

Test the servlet

http://localhost:8080/security-web/se


The console prints

User: sun
Saved


Close and open the browser again, login with the user 'ming'

The console prints

javax.ejb.EJBAccessException

Then try to login with an nonexistent user

The console prints

java.lang.SecurityException