- Whitehorses - http://blog.whitehorses.nl -

Weblogic web application container security part 1

Tweet [1]

With theĀ  Weblogic server we have two ways to implement security on a J2EE web application. The first is the normal container security and the second is ADF Security. In part 1 I will explain the container security and in part 2 the ADF Security.
To test this, I first added a testuser called edwin and a test group called users to the DefaultAuthenticator Authentication Provider. The user edwin is member of the group users.
first step is to add a security constraint on a url and define that you need to have the role User_role to authenticate

    <security-constraint>
        <web-resource-collection>
            <web-resource-name>sec</web-resource-name>
            <url-pattern>/</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <role-name>User_role</role-name>
        </auth-constraint>
    </security-constraint>
    <login-config>
        <auth-method>BASIC</auth-method>
        <realm-name>myrealm</realm-name>
    </login-config>
    <security-role>
        <role-name>User_role</role-name>
    </security-role>

Because we don’t have the role User_role in Weblogic so we need to add a mapping between User_role role ( defined in the web.xml ) and the Weblogic group users. For this we need to add a weblogic.xml deployment descriptor (located in the WEB-INF )

<?xml version = '1.0' encoding = 'windows-1252'?>
<weblogic-web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                  xsi:schemaLocation="http://www.bea.com/ns/weblogic/weblogic-web-app.xsd"
                  xmlns="http://www.bea.com/ns/weblogic/weblogic-web-app">
  <security-role-assignment>
    <role-name>User_role</role-name>
    <principal-name>users</principal-name>
  </security-role-assignment>
</weblogic-web-app>

We solved the Authentication part but the next step is Authorization part. For this we need to add a managed bean where we retrieve and evaluate the roles of the authenticated user. The hard part is that the principal does not give back the user roles. Off course we can evaluate is the user has a role ( with isUserInRole ), but then you need to know the role name ( in most cases this is enough). To get all the User roles, we need to retrieve the Weblogic Subject and get all the principals and look at the class of the principal ( it can be a instance of WLSGroupImpl or WLSUserImpl ). Be aware you will get the Weblogic groups and not the mapped names of the web.xml or weblogic.xml.
Here is the managed bean ( request scope)

package nl.whitehorses.sec.bean;

import java.security.Principal;

import java.util.ArrayList;
import java.util.Set;

import javax.faces.context.FacesContext;
import javax.security.auth.Subject;

import weblogic.security.Security;
import weblogic.security.SubjectUtils;
import weblogic.security.principal.WLSGroupImpl;
import weblogic.security.principal.WLSUserImpl;

public class SecurityBean {

    public SecurityBean() {

        Subject subject = Security.getCurrentSubject();
        Set<Principal> allPrincipals = subject.getPrincipals();
        for (Principal principal : allPrincipals) {
            if ( principal instanceof WLSGroupImpl ) {
                System.out.println("found role: "+principal.getName());
                roles.add(principal.getName());
            }
            if ( principal instanceof WLSUserImpl ) {
                System.out.println("found user: "+principal.getName());
                user = principal.getName();
            }            
        }        
    }
    
    private ArrayList<String> roles = new ArrayList<String>();
    private String user = null;

    public String getCurrentUserRoles() {
        String curRoles = "";
        for (String role : roles) {
            curRoles = curRoles +", "+role;
        }
        return curRoles;
    }

    public boolean isWlsUserRole() {
     for (int i=0; i < roles.size() ; i++ ){
        if ( "users".equalsIgnoreCase(roles.get(i)) ){
           return true;
        }
      }
      return false;
    }

    public boolean isContainerUserRole() {
      if (FacesContext.getCurrentInstance().getExternalContext().isUserInRole("User_role")){
           return true;
      }
      return false;
    }

    public String getCurrentUser() {
        return user;
    }
}

and last the JSF page where I use this managed bean

<?xml version='1.0' encoding='windows-1252'?>
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.1"
          xmlns:f="http://java.sun.com/jsf/core"
          xmlns:af="http://xmlns.oracle.com/adf/faces/rich">
  <jsp:directive.page contentType="text/html;charset=windows-1252"/>
  <f:view>
    <af:document id="d1">
      <af:form id="f1">
        <af:panelHeader text="Start" id="ph1">
          <af:panelFormLayout id="pfl1">
            <af:inputText label="User" id="it1"
                          value="#{SecurityBean.currentUser}"/>
            <af:inputText label="Roles" id="it2"
                          value="#{SecurityBean.currentUserRoles}"/>
            <af:inputText label="WLS Role" id="it3"
                          value="got the users role from weblogic"
                          rendered="#{SecurityBean.wlsUserRole}" columns="80"/>
            <af:inputText label="JAAS Role" id="it4"
                          value="got the User_role mapped by weblogic.xml"
                          rendered="#{SecurityBean.containerUserRole}"
                          columns="80"/>
          </af:panelFormLayout>
        </af:panelHeader>
      </af:form>
    </af:document>
  </f:view>
</jsp:root>

with this as result.
[2]
In Part 2 [3] I will explain ADF Security and then you can see how easy Security is in ADF and that ADF has a lot more security options then the standard container security.