Over a million developers have joined DZone.

Simple Form Login Page With Apache Sling

How to create a login page in Java using Apache Sling and Maven.

· Java Zone

Learn more about the advantages of moving from a monolithic to microservices architecture.  Brought to you in partnership with IBM.

In this post we will show a simple example on how to create a login page with Apache Sling and define which paths will ask for the user to login to the site using our login page.

In order to execute this, we need to have the Sling Lauchpad running on our machine. For this we can download the binary from the Apache Sling website in Downloads Section. If you have Docker installed on your machine you can use the Sling docker image.

Once you have your Sling Launchpad running we can now create our project.

Apache Sling provides some Maven Archetypes to create Sling Based projects. We are going to use sling-intitial-content-archetype. The complete list of the available archetypes can be found here.

By using Eclipse we need to go:  File -> New.. -> Project -> Maven -> Maven Project 

New Project

Then in the archetype selection, choose the sling-intitial-content-archetype.

Archetype Selection

Then enter the groupid and artifactid for your project.

Create a Login Page 

For the login page I’ve used a Bootstratp Form.

First we are going to create the rendering script for the login page. For this we will create the following folder structure on  src/main/resources/SLING-INF :  sling-form-login/login 

Inside this folder we create the login.html. This will be the script that will be called when the login page is requested. We can see it below:

  <div class="container">
        <div class="row">
            <div class="col-sm-6 col-md-4 col-md-offset-4">
                <h1 class="text-center login-title">Sign in to continue to Bootsnipp</h1>
                <div class="account-wall">
                    <img class="profile-img" src="https://lh5.googleusercontent.com/-b0-k99FZlyE/AAAAAAAAAAI/AAAAAAAAAAA/eu7opA4byxI/photo.jpg?sz=120"
                    <form method="POST" action="/j_security_check" autocomplete="off" class="form-signin">
                    <input type="text" class="form-control" placeholder="Username" required autofocus name="j_username">
                    <input type="password" class="form-control" placeholder="Password" required name="j_password">
                    <input type="hidden" name="sling.auth.redirect" value="/content/page/home.html">
                    <button class="btn btn-lg btn-primary btn-block" type="submit">
                        Sign in</button>
                    <label class="checkbox pull-left">
                        <input type="checkbox" value="remember-me">
                        Remember me
                    <a href="#" class="pull-right need-help">Need help? </a><span class="clearfix"></span>
                <a href="#" class="text-center new-account">Create an account </a>

The most important parts of this snippet are:

  • The form action set to: /j_security_check
  • The username input set to: j_username
  • The password input set to j_password

Now we need to create a node in the repository that will use this rendering script. For this we need to create a new file under SLING-INF/content: login.json .

With the below content:

    "jcr:primaryType" : "nt:unstructured",
    "sling:resourceType" : "sling-form-login/login"

With that JSON file we are defining a new node in the repository which have nt:unstructured as primary type and sling-form-login/login as resource type. With this configuration we’ve defined that this node we will use the rendering script we defined in the last step.

In order to test if our configurations are ok, we need to deploy our project into Sling Launchpad. Before we deploy it, we need to make some adjustments in our pom.xml. In the maven-bundle-plugin we will have the following config:


Once we change it, we can deploy our project by running the following maven command:  mvn clean install -P autoInstallBundle .

If everything goes well then we can access the following url:  http://localhost:8080/login.html .

And we can see our login page:

Login Page

Create a Content Page

Now we are going to create the page we want to protect using our login screen. This will be a simple page that will display the current user login name.

Basically we are going to use the same steps we followed for the login page. 

Create the Rendering Script at /SLING-INF/sling-form-login/page

<%@ page session="false" %>
<%@ page import="javax.jcr.*,
<%@ taglib prefix="sling" uri="http://sling.apache.org/taglibs/sling/1.0" %>
<sling:defineObjects />
    String userID = resourceResolver.adaptTo(javax.jcr.Session.class).getUserID();

            Hello, <%=userID%>

Basically this JSP gets the current user and displays its userId.

Then create the node that will use the rendering script at /SLING-INF/content/page/home.json

    "jcr:primaryType" : "nt:unstructured",
    "sling:resourceSuperType" : "sling-form-login/page"

Then we deploy our project again. If everything is fine than can access the following URL: http://localhost:8080/content/page/home.html.

And see this:

Login Page

If you were logged in, then you can see your user ID.

Set the home.html as a Protected Page

To define that our content page(home.html) requires authentication, we need to configure the Sling Authentication Service.

We can do this by using the Felix Console:  http://localhost:8080/system/console/configMgr

Then find the Sling Authentication Service. You you can see the details below:

Sling Authentication Service

We need to set the Authentication Requirements (sling.auth.requirements) by entering the paths that will require authentication. Another possible way to do this is to create a sling:OsgiConfig node in the repository. This is the way we will use for this example.

We will create a node which uses the PID as its name. We can find the PID in the bottom of the above screenshot where we see Persistent Identity (PID), so we are going to create a new node under: /SLING-INF/sling-form-login/install  

And name it as: org.apache.sling.engine.impl.auth.SlingAuthenticator.json  

And its contents will look like this:

    "jcr:primaryType": "sling:OsgiConfig",
    "sling.auth.requirements": [

With this configuration, we are saying that all paths starting with /content/page require authentication to access them. We set this by adding the plus (+) sign before the path. If we used the minus (-) we were saying that the path doesn’t require authentication.

Now if we deploy our last change, when we try to access the content page we created we will be redirected to a login screen, in this case the default login page of the system.

Default Login Screen

If we log with admin/admin or any other user you have. It will redirect to our page and display the username:

Logged User Page

Great!! Now let’s take the next step.

Define the Login Screen

The default login screen used by Sling is defined in the Apache Sling Form Based Authentication Handler. It has a property where we can set the login form as we can see below:

Form Authentication Handler Config

The property we need to change is Login Form(form.login.form). 

To do this we will do something similar as we did for the Authentication Service, we will create a sling:OsgiConfig node using the PID as node name in this case:  org.apache.sling.auth.form.FormAuthenticationHandler.json 

Its contents can be seen below:

    "jcr:primaryType": "sling:OsgiConfig",
    "form.login.form": "/content/login.html"

After deploying our last change, if we try to access the home.html page not logged in we are redirected to our custom login page as we can see below:

Form Authentication Handler Config

If we login then we will see home.html with our userId.

If You Are Using Docker

In order to execute the Sling image, first we need to download the image: docker pull apachesling/sling  

Then to create a container using the image: docker run -d -p 8080:8080 apachesling/sling  

Then it will start a container and expose the port 8080. If you are using docker-machine(that’s my case) you can not access localhost once the container is running the docker-machine VM.

You need to find the docker-machine IP. You cand do this using the following command: docker-machine ip default  

Also if you are on docker-machine remember to change you pom.xml to point to your docker-machine IP in order to be able to deploy the project.

That’s it! I hope you enjoyed this post. You can find all the source code on my GitHub.

Thanks, See you in the next post.

From Idea to Application gives you the architecture to quickly build, manage and run a range of applications (web, mobile, big data, new smart devices, etc.) on an open-standard, cloud-based platform. See why developers are using IBM Bluemix. Brought to you in partnership with IBM.


Published at DZone with permission of Francisco Ribeiro, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

The best of DZone straight to your inbox.

Please provide a valid email address.

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}