Authenticating and Authorizing Users in Java EE 6 Web Applications Running on WebLogic Server 12c

Overview

    Purpose

    This tutorial covers how to secure a Java EE 6 Web Application with form-based authentication and role-based authorization. It shows how to create a login form with JavaServer Faces as the client to collect user and password data and how to authorize certain roles that access a Servlet.

    Also shows how to add users to the WebLogic Server 12c and map them to the Web Application roles that will be used in the authentication and authorization processes.

    Time to Complete

    Approximately 60 minutes

    Introduction

    Some resources of a Web Application require some type of access restriction. Enterprises often demand that their Web Applications or part of them be secured and only allow the access to certain users or roles.

    To verify the identity of a user or entity the authentication process is used. Authentication is the process that ensures the users are who they say they are. And to ensure that users have permission to perform operations or access data the authorization process is used.

    When a Web client requests access to a protected resource there is an initial authentication of the Web client with the Web server based on authentication data such as user name and password. The Web server validates the data and if it is successful the Web server fulfills the original request by delivering the requested content to the calling Web page. Otherwise a "not authorized" error message is returned to the Web client.

    In Java EE, the component containers are responsible for providing application security. A container provides two types of security: declarative and programmatic. Declarative security uses either deployment descriptors or annotations and programmatic security is embedded in an application.

    In this tutorial you will practice both types of security: You will specify security constraints using declarative security by creating a deployment descriptor while developing a login form. And you will manage the login process using programmatic security in a ManageBean that uses request.login and request.logout methods programmatically. You will check caller identity also programmatically. At the end of the tutorial, you will return to practice declarative security when using annotations to restrict the access to a Servlet to certain roles.

    Programmatic security is useful when declarative security alone is not sufficient to express the security model of an application. In this tutorial you will use the HttpServletRequest interface methods. These methods allow components to make business-logic decisions based on the security role of the caller, who is previously registered in the WebLogic Server realm.

    Scenario

    In this tutorial, you perform the following:

    • Add users to the WebLogic Server
    • Specify security constraints
    • Create a login form
    • Create a Managed Bean to control the login form
    • Secure the access to a Servlet using Annotations

    Prerequisites

    Before starting this tutorial, you should:

    • Download and install Java JDK 7 from this link.
    • Download and install NetBeans IDE 7.2 from this link.
    • Complete the first three sections of this OBE to download, install and configure WebLogic Server 12c zip distribution file in NetBeans.

Adding Users in the WebLogic Server

    In this section, you will add users in the WebLogic Server realm. Then you will authenticate and authorize these users in the next section of this tutorial.

    Start NetBeans. Open the Services Window (Window -> Services).

    Expand the Servers folder.

    Right-click Oracle WebLogic Server. Click Start.

    Right-click Oracle WebLogic Server. Click View Admin Console.

    In the Admin Console, enter weblogic for the username and welcome1 for the password. (Use the username and password for your admin account, if they are different.)

    Click Login.

    In the left pane, select Security Realms.

    In the Summary of Security Realms page select myrealm.

    WebLogic Server includes myrealm, an embedded LDAP server that you will use in this tutorial to manage users. You can configure a JDBC authentication realm and use it instead of myrealm.

    In the Settings for myrealm page, click the Users and Groups tab.

    The Users table shows the current users in the WebLogic Server realm.

    Click New.

    Enter webuser for Name.

    Enter welcome2 for Password.

    Re-enter welcome2 for Confirm Password.

    Click OK.

    The Description field is optional.

    Click New again. You will create the admin user now.

    Enter webadmin for Name.

    Enter welcome3 for Password.

    Re-enter welcome3 for Confirm Password.

    Click OK.



    You have registered the users webuser and webadmin within your WebLogic Server instance.

Specifying Security Constraints in a Web Project

    In this section, you will create a new Web project and add security constraints to the web.xml and weblogic.xml file.

    Creating a New Java Web Project

      In NetBeans, click File -> New Project.

      Select Java Web from Categories and Web Application from Projects. Click Next.

      Enter SecureDukeRealm for Project Name.

      Set the Project Location to D:\NetBeansProjects or the folder path that you want for your NetBeans projects.

      Click Next.

      Verify that Oracle WebLogic Server is selected as the Server.

      Verify that Java EE version is Java EE 6 Web.

      Check the box for Enable Contexts and Dependency Injection.

      Uncheck the default box to Set Source Level to 6.

      Click Next.

      Select JavaServer Faces as the Framework. Click Finish.

      NetBeans creates SecureDukeRealm Web project into your projects with an entry point in the index.xhtml file. You will secure this file by adding constraints to web.xml and weblogic.xml files in the following section.

    Specifying Security Constraints

      In this section, you will specify the security constraints of your Web Aplication in the web.xml file. You will be using declarative security since you will create a deployment descriptor. You will also map the users that you created in the WebLogic Server realm to the roles in the Web Application by adding entries to the weblogic.xml file.

      Add the following code to the web.xml file, which is under the WEB-INF folder in your project:

           <security-constraint>
              <display-name>Protected Area</display-name>
              <web-resource-collection>
                  <web-resource-name>Protected Area</web-resource-name>
                  <description/>
                  <url-pattern>/*</url-pattern>
              </web-resource-collection>
              <auth-constraint>
                  <description/>
                  <role-name>User</role-name>
              </auth-constraint>
           </security-constraint>
           <login-config>
              <auth-method>FORM</auth-method>
              <realm-name>myrealm</realm-name>
              <form-login-config>
                  <form-login-page>/faces/login.xhtml</form-login-page>
                  <form-error-page>/faces/login.xhtml</form-error-page>
              </form-login-config>
          </login-config>
           <security-role>
              <description/>
              <role-name>User</role-name>
          </security-role>
          <security-role>
              <description/>
              <role-name>Admin</role-name>
          </security-role>


      Explanation of the XML code

      By entering /* under the <security-constraint><web-resource-collection><url-pattern>  tag, you are restricting the access to all the elements in your Web Application. You can use the <url-pattern> tag to give total or partial access to the web resources:


      In the <auth-constraint><role-name> tag you are authorizing to the User role to access the Protected Area (The entire Web Application):


      Also, you are specifying that your Web Application is using the FORM authentication type under the <login-config><auth-method> tag and that the realm you are using is myrealm with the <realm-name> tag:


      You define the login and error pages under the <form-login-config> tag:


      Two roles are defined under the <security-role><role-name> tag: User and Admin:


      These two roles are linked to the users that you created in the WebLogic Server in the weblogic.xml file, which is done in the following section.

      Add the following code to the weblogic.xml file, which is under the WEB-INF folder in your project:

          <security-role-assignment>
              <role-name>User</role-name>
              <principal-name>webadmin</principal-name>
              <principal-name>webuser</principal-name>
          </security-role-assignment>
          <security-role-assignment>
              <role-name>Admin</role-name>
              <principal-name>webadmin</principal-name>
          </security-role-assignment>

      The two users that you defined in the WebLogic Server realm webadmin and webuser are mapped here to the roles User and Admin, defined for this Web Application in the web.xml file.

      Under the tag <principal-name>, you can define groups as well to avoid register each one of the users for your Web Application.

      Figure 1 shows the roles for the Web Application and which WebLogic Server users correspond to each of the roles.

      Figure 1: Roles for the SecureDukeRealm Application. How only the Admin role has access to a Servlet is shown in the last section of this tutorial.

Creating and Managing the Login Form

    In this section you will create the login page and a ManagedBean to manage the login page.

    Creating the Login Page

      Right-click the project. Select New -> Other.

      Choose Java Server Faces from Categories and JSF Page as the file type. Click Next.

      Enter login for the File Name.

      Click Finish.

      NetBeans creates the login.xhtml Facelet under the Web Pages folder in your project.

      Add the following code to the login.xhtml file, replacing the current content under the <h:body> tag:

           
              <h2>Hello, please log in:</h2>
              <h:form>
                  <h:panelGrid columns="2">
                      <h:outputLabel for="j_username"
                                     value="Please type your user name : "/>
                      <h:inputText id="j_username" value="#{loginBean.userName}"
                                   autocomplete="off" size="20"/>

                      <h:outputLabel for="j_password"
                                     value="Please type your password : " />
                      <h:inputSecret id="j_password" value="#{loginBean.password}"
                                     autocomplete="off" size="20"/>
                  </h:panelGrid>
                  <h:panelGroup>
                      <h:commandButton value="Submit" action="#{loginBean.login}"
                                       type="submit"/>
                      <h:commandButton value="Clear" type="reset"/>
                  </h:panelGroup>
              </h:form>
              <h:form styleClass="settings-form" rendered="#{request.userPrincipal ne null}">
                  You are logged in as #{request.userPrincipal.name}
                  <h:commandButton action="#{loginBean.logout}" value="Logout"/>
              </h:form>

      4.1. Change <title> content to Login Page:

      The login.xhtml is a login form built with JavaServer Faces to collect user and password data. When user clicks Submit button the login method of loginBean is called as an action.  As you will see in the next section, the loginBean.login method uses the login method of the Servlet 3.0 HttpServletRequest interface, and that enables you to authenticate users for a web application programmatically.

      The login.xhtml also considers when a user is already logged in, and in that case the "You are logged in as ..." legend will be shown below the login form and a button will allow the current user to log out by calling the loginBean.logout method.

    Creating the Login Managed Bean

      Right-click the project. Select New -> Other.

      Choose Java Server Faces from Categories and JSF Managed Bean as the file type. Click Next.

      Enter LoginBean for Class Name.

      Enter com.example.beans for Package.

      Select request for Scope.

      Click Finish.

      Add userName and password variables to the LoginBean class:

            private String userName;
            private String password;

      Right-click LoginBean source. 

      Click Insert Code.

      Click Getter and Setter...

      Check password and userName.

      Click Generate.

      Add the following login method to the LoginBean class:

          public String login() {
              ExternalContext externalContext =
                      FacesContext.getCurrentInstance().getExternalContext();
              HttpServletRequest request = (HttpServletRequest) externalContext.getRequest();
              try {
                  request.login(userName, password);
                  return "index";
              } catch (ServletException ex) {
                  Logger.getLogger(LoginBean.class.getName()).log(Level.INFO,
                          "Failed to log in {0}", userName);
                  FacesContext facesContext = FacesContext.getCurrentInstance();
                  FacesMessage facesMessage = new FacesMessage(
                          "Failed to log in");
                  facesMessage.setSeverity(FacesMessage.SEVERITY_ERROR);
                  facesContext.addMessage(null, facesMessage);
                  return null;
              }
          }

      8.1. Click Ctrl+Shift+I and click OK in the Fix All Import window to import the missing classes.

      Login method uses the Servlet 3.0 request.login method to log in with the passed user name and password.

      Add the following logout method to the LoginBean class, which uses the HttpServletRequest.logout method:

          public String logout() {
              ExternalContext externalContext =
                      FacesContext.getCurrentInstance().getExternalContext();
              HttpServletRequest request = (HttpServletRequest) externalContext.getRequest();
              try {
                  request.logout();
                  return "login";
              } catch (ServletException ex) {
                  Logger.getLogger(LoginBean.class.getName()).log(Level.SEVERE,
                          "Failed to logout", ex);
              }
              return null;
          }

      Logout method uses the Servlet 3.0 request.logout method to log out the current user.

Updating the Index File and Opening the Web Application

    In this section, you will update the index.xhtml page to allow user to log out from the current user. You also will deploy the Web Application and open the application on a Web browser.

    Updating the Index File

      Add the following code to the index.xhtml file, which is under the Web Pages folder in your project:

              <h:graphicImage url="Duke_Caesar.gif" alt="Duke as a caesar"/>
              <h2>Hello, you are logged in as #{request.userPrincipal.name}<br/></h2>
              <h:form styleClass="settings-form" rendered="#{request.userPrincipal ne null}">
                  <h:commandButton action="#{loginBean.logout}" value="Logout"/>
              </h:form>

      1.1. Change <title> content to Secure Duke Realm:

      Copy the Duke's image that you can download it from here to your Web folder under your NetBeans project:

    Deploying and Opening the Web Application

      Right-click the project. Click Deploy.

      WebLogic Server starts and deploys the application.

      Open a browser and enter the following URL: http://localhost:7001/SecureDukeRealm/

      Enter webuser for the username in the login form.

      Enter welcome2 for the password.

      Click Submit.

      You can see the content of index.xhtml since you are authorized for the web application as webuser:

      Click Logout.

      Enter webadmin for the username in the login form.

      Enter welcome3 for the password.

      Click Submit.

      You can see the content of index.xhtml since you are authorized for the web application as webadmin:

Securing a Servlet Using Annotations and Opening the Web Application

    In this section, you will create Servlet using the @ServletSecurity annotation to authorize the access to the Servlet's URL only to the Admin role.

    Securing a Servlet Using Annotations

      Right-click the project. Select New -> Servlet...

      Enter AdminDukeRealmServlet for the Class Name.

      Enter com.example.servlets for the Package.

      Click Finish.

      NetBeans creates the AdminDukeRealmServlet.java servlet.

      Add the following line in the AdminDukeRealmServlet class:

      @ServletSecurity(@HttpConstraint(rolesAllowed = {"Admin"}))

      3.1. Click Ctrl+Shift+I to import the missing classes.

      If you use the @ServletSecurity annotation, you do not need to specify settings in the deployment descriptor.

      Add the following code into the processRequest method in the AdminDukeRealmServlet class, substituting the content between the try clause :

                  out.println("<html lang=\"en\">" + "<head><title>Hello</title></head>");
                  out.println(
                          "<body  bgcolor=\"#ffffff\">"
                          + "<img src=\"Duke_Caesar.gif\" alt=\"Duke as a caesar\">"
                          + "<form action=\"LogoutServlet\" method=\"get\">"
                          + "<h2>Hello, you are logged in as ");
                  out.println(request.getUserPrincipal().getName());
                  out.println(" and you are in a secured URL</h2>");
                  out.println("<p></p>" + "<input type=\"submit\" value=\"Logout\"/>");
                  out.println("</form></body></html>");
         

      You are using the request.getUserPrincipal.getName method to identify the user programmatically.

      You will need to create a new Servlet to do the logout of the button in this Servlet by invalidating the current session, which is done in the following steps.

      Right-click the project. Select New -> Servlet...

      Enter LogoutServlet for the Class Name.

      Enter com.example.servlets for the Package.

      Click Finish.

      NetBeans creates the Servlet LogoutServlet.java.

      Add the following code into the processRequest method in the LogoutServlet class, substituting the content between the try clause :

                  HttpSession session = (HttpSession) request.getSession(false);
                  if (session != null) {
                      session.invalidate();
                  }
                  response.sendRedirect("login.xhtml");

      7.1. Click Ctrl+Shift+I to import the missing classes.


      Click Ctrl+S to save the application.

    Opening the Web Application and Testing the Access to the Secured Servlet

      Log in to the Web Application.

      Open a browser and enter the following URL: http://localhost:7001/SecureDukeRealm

      Enter webadmin for the username in the login form.

      Enter welcome3 for the password.

      Click Submit.

      You are logged in as webadmin.

      Accessing the Servlet as a webadmin.

      Enter the following URL in your Web browser: http://localhost:7001/SecureDukeRealm/AdminDukeRealmServlet

      You can see the content of the Servlet since you are authorized as webadmin.

      Click Logout.

      Login to the Web Application as a webuser.

      Enter webuser for the username in the login form.

      Enter welcome2 for the password.

      Click Submit.

      Enter the following URL in your Web browser: http://localhost:7001/SecureDukeRealm/AdminDukeRealmServlet

      You get an error message because you are trying to access the URL of a Servlet that is allowed only to the Admin role.

Summary

    In this tutorial, you have learned how to:

    • Add users to the WebLogic Server
    • Specify security constraints
    • Create a login form
    • Create a Managed Bean to control the login form
    • Secure the access to a Servlet using Annotations

    Resources

    Credits

    • Curriculum Developer: Edgar Martinez

To help navigate this Oracle by Example, note the following:

Hiding Header Buttons:
Click the Title to hide the buttons in the header. To show the buttons again, simply click the Title again.
Topic List Button:
A list of all the topics. Click one of the topics to navigate to that section.
Expand/Collapse All Topics:
To show/hide all the detail for all the sections. By default, all topics are collapsed
Show/Hide All Images:
To show/hide all the screenshots. By default, all images are displayed.
Print:
To print the content. The content currently displayed or hidden will be printed.

To navigate to a particular section in this tutorial, select the topic from the list.