Last updated by abrighton 4 years ago

JSecurity Plugin - Quick Start Guide

This guide will quickly get you up and running with a standard setup for your web application's authentication and authorisation needs. Note that JSecurity is more flexible than described in this example, so please do visit the reference documentation later.

This guide is for the 0.2 release of the plugin. Guides for previous versions can be found here:

Installation

Getting started is simple - just follow these steps:

First install the plugin into your project:

grails install-plugin jsecurity

Next, generate some standard domain classes:

grails quick-start

This second step will set you up with some domain classes used to store user, role, and permission information. Note that all these classes start with the prefix "Jsec" by default, but you can change this (if you are using Grails 1.0.3 or newer) by passing an option to the command:

grails quick-start --prefix=""
In this example, the classes will all be created with the prefix "Jsec".

Securing your web application

Since this is the quick start guide, we need some users and other security information for testing. This side of things is handled by the realms, which can use all manner of information sources such as LDAP, the file system, or a remote service. The quick-start command has just installed a realm that uses Grails domain classes to store that data, so that is what we will base the rest of the guide on.

Setting up the users

We are now going to create some users and roles in BootStrap so that we can actually test the access control provided by JSecurity. Assuming that the realm has been installed with the default prefix of "Jsec", add the following block of code to the init closure:

import org.jsecurity.crypto.hash.Sha1Hash

// Administrator user and role. def adminRole = new JsecRole(name: "Administrator").save() def adminUser = new JsecUser(username: "admin", passwordHash: new Sha1Hash("admin").toHex()).save() new JsecUserRoleRel(user: adminUser, role: adminRole).save()

// A normal user. def userRole = new JsecRole(name: "User").save() def normalUser = new JsecUser(username: "phil", passwordHash: new Sha1Hash("password").toHex()).save() new JsecUserRoleRel(user: normalUser, role: userRole).save()

// Give another user the "User" role. normalUser = new JsecUser(username: "alice", passwordHash: new Sha1Hash("changeit").toHex()).save() new JsecUserRoleRel(user: normalUser, role: userRole).save()

The above code sets up three users and two roles such that we have:

Administrator: "admin"
User:          "alice", "phil"

Declaring access control

The data is now there, so what comes next? We need to tell the system who has access to what, and we do that inside a Grails filter. So, create a new file grails-app/conf/SecurityFilters.groovy and copy in the code below.

Note that the accessControl blocks below are method calls that return a boolean. This return value needs to be returned from the before closure. If the accessControl blocks are the last expression in the before closure, we do not need to preceed them with the return keyword.

class SecurityFilters {
    def filters = {
        // Ensure that all controllers and actions require an authenticated user,
        // except for the "public" controller
        auth(controller: "*", action: "*") {
            before = {
                // Exclude the "public" controller.
                if (controllerName == "public") return true

// This just means that the user must be authenticated. He does // not need any particular role or permission. accessControl { true } } }

// Creating, modifying, or deleting a book requires the "Administrator" // role. bookEditing(controller: "book", action: "(create|edit|save|update|delete)") { before = { accessControl { role("Administrator") } } }

// Showing a book requires the "Administrator" *or* the "User" roles. bookShow(controller: "book", action: "show") { before = { accessControl { role("Administrator") || role("User") } } } } }

Now create a "Book" domain class if you do not already have one, and scaffold it with grails generate-all Book . Run the application and try to access the various pages. All the "book" pages will redirect you to a login page until you successfully authenticate. Go ahead and test out the various options using the users that we defined in BootStrap .

In Grails 1.1, with the config "jsecurity.legacy.filter.enabled = true", you now must make sure you always have a controller, for example localhost:8080/myApp won't work. Goto "grails-app/conf/UrlMappings.groovy" and define:

"/"(controller:"public", action:"index")
Of course, you must then write your PublicController.

You now have a secure web application!

GSP tags

The application's pages are now secured, but how do we make the pages themselves aware of the current user and his privileges? The plugin provides a comprehensive tag library that provides most of the features you will need. Take as an example the typical line on the page that shows the user's name and a link for signing out. The ideal place for this is in the layout, so try adding this to your "main.gsp":

<jsec:isLoggedIn>
  <div>Logged in as: <jsec:principal/> (<g:link controller="auth" action="signOut">sign out</g:link>)</div>
</jsec:isLoggedIn>

The <jsec:isLoggedIn> tag will only write its contents to the output if the user is currently logged in (authenticated). The second tag, <jsec:principal/> , prints the current principal to the page. For this example, the principal is the username that was used to log in.

In case you are wondering what a "principal" is, here is a quick description: it is an identifier for a user, such as a username, a first name and last name, a public key, or anything else. In fact, a user can have more than one principal and it is the realms that determine which ones are available. The database realm created by the {{quick-start}} command simply associates the login name with the user, and this is the only principal it provides. However, you could easily modify the realm to associate a full name as well.

OK, so after that little digression, here's a quick summary of the available tags:

  • isLoggedIn : only displays its contents if the user is logged in.
  • isNotLoggedIn : only displays its contents if the user is not logged in.
  • authenticated : synonym for isLoggedIn .
  • notAuthenticated : synonym for isNotLoggedIn .
  • user : only displays its contents if the user is recognised, either via "remember me" or login.
  • principal : displays the current user's principal, e.g. username.
  • hasRole : only displays its content if the current user is authenticated and has the given role.
  • lacksRole : the inverse of hasRole .
  • hasPermission : only displays its content if the current user is authenticated and has the given permission.
  • lacksPermission : the inverse of hasPermission .

The login screen

This release of the plugin comes with an AuthController and a login page. Unauthenticated users are redirected to this page when they attempt to access a secure page. The controller also comes with actions for logging out, signOut , and unauthorised access, unauthorised . By default, signOut redirects back to the home page, but you are encouraged to customise the action and view to your own requirements. The same goes for the unauthorised action.

For example:

def signOut = {
    // Log the user out of the application.
    SecurityUtils.subject?.logout()

// Redirect to the main book page. redirect(controller:"book", action:"index") }

// Just show the "unauthorised.gsp" view. def unauthorised = {}

Using Jsecurity from a controller or domain class

Using Jsecurity from a controller or domain class is very similar to using it in a GSP, only you're calling functions instead of tags.

You will need to import the package: import org.jsecurity.*;

Then you can get the current user and check if the user was authenticated. Assuming you did the Jsecurity quick start using "grails quick-start" when you installed the Jsecurity plugin, and you named your user class JsecUser, the code would look like this:

def subject = SecurityUtils.getSubject();
if(subject.authenticated){
     JsecUser currentUser = JsecUser.findByUsername(SecurityUtils.getSubject()?.getPrincipal());
}

Or, more succinctly:

def subject = SecurityUtils.getSubject();
if (subject.authenticated) {
     createdBy = JsecUser.findByUsername(subject.principal)
}

For more information, refer to the JSecurity website.