grails create-app project_name
grails install-plugin jsecurity
Then we use the
quick-start
option, available once the plugin is installed, to generate JSecurity domain classes, controller and realm.
grails quick-start
We can follow the JSecurity Quick Start guide to create a functional security application or use the files present to customize and only take what is required.
Authentication
For the login authentication, we'll need the
User
class, the Auth
controller and the DbRealm
.- The
User
class will need a username and password field. The password field must be hashed, SHA1 is the default. - For the
Auth
controller, the important methods aresignIn
andsignOut
. ForsignIn
, the important lines are theauthToken
definition, thejsecSecurityManager
login and thetry-catch
block. - Authentication occurs in the
DbRealm
. The important lines in theauthenticate
method are theaccount
definition and thecredentialMatch
. You may customize theauthToken
class by changing thestatic
line, replacing the default with your own class. credentialMatch
defaults to SHA1 hashing, to change it, modifygrails-app/conf/spring/resources.groovy
and add the linecredentialMatcher(org.jsecurity.authc.credential.hashMatcher)
. ReplacehashMatcher
with the hash class of your choice.
Roles
Roles depend on the hasRole method of the realm. This method accepts a principal, usually a username, and a rolename. The output is a simple true or false boolean, making the logic inside the method completely up to the programmer. The classes generated by the quick-start are not all necessary. We can easily use a variable in the user class to determine the role, modifying the hasRole method as required, thus no additional classes are needed.
For this project, we are using the default
hasRole
method and keeping the Role
as well as the UserRoleRel
class. This, along with the User
class, allows us to have users and roles, assigning the users to a role in a many-to-one relationship. Refer to the JSecurity Quick Start guide for the way to bootstrap it.Authorization
Having users and roles, we can now set up proper access control by creating a security filter file,
grails-app/conf/SecurityFilters.groovy
. Filter rules cannot overlap in actions, just modify the accessControl
to include the desired roles. The rules return true or false, allowing or denying access.Security Filter Example
import org.jsecurity.SecurityUtils
// Customise the interceptor behaviour by implementing onNotAuthenticated() and onUnauthorized() methods in your filters class.
// Default behaviour remains as before (redirect to login page for an unauthenticated user, redirect to unauthorized page for unauthorized access).
class SecurityFilters {
def filters = {
// Ensure that all controllers and actions require an authenticated user,
// except for a few controllers
auth(controller: "*", action: "*") {
before = {
// Exclude these controllers.
if ((controllerName == "search" && actionName == "unboundSearch") || (controllerName == "business" && actionName == "show") ||
(controllerName == "user" && actionName == "signup")) return true
// This just means that the user must be authenticated. He does
// not need any particular role or permission.
accessControl { true }
}
}
// Roles return true or false
// Add reviews to businesses. Only Administrators or Users can do this
addReview(controller: "review", action: "create") {
before = {
accessControl {
role("Administrator") || role("User")
}
}
}
// Add pets to users
addPets(controller: "pet", action: "(create|save)") {
before = {
accessControl {
def user = User.findByUserName(SecurityUtils.subject.principal)
def allowAccess = false
if (role("Administrator")) {
allowAccess = true
}
else if (params.id.toLong() == user.id) {
allowAccess = role("Business User") || role("User")
}
return allowAccess
}
}
}
}
}
Permissions
Permissions offer finer access control, like read, update, delete. Roles can be considered as named collections of permissions, like administrator, user, superuser. Nothing was done with permissions, it was entirely a role-based affair. Refer to the documentation for usage.