3
votes

I am working on a grails application for the first time and I now want to protect some pages to be viewed only by admins, and give some permissions to other users.

I am using Apache Shiro plugin for grails.

My sample code in the bootstrap looks like this

class BootStrap {

def init = { servletContext ->
    def adminRole

    if(ShiroRole.findByName("Admin".isEmpty())){
        adminRole = new ShiroRole(name: "Administrator")
        adminRole.addToPermissions("*:*")
        adminRole.addToPermissions("admin")

        adminRole.save()

// 'user' now has all administrator rights }

    if (ShiroUser.findAllByUsername("user").isEmpty()) {
        def user = new ShiroUser(username: "user", passwordHash: new Sha256Hash("pass").toHex())
        user.addToPermissions("*:*")
        user.addToRoles(adminRole)

        user.save()

    }

    if (ShiroUser.findAllByUsername("Guest").isEmpty()) {
        def user = new ShiroUser(username: "Guest", passwordHash: new Sha256Hash("pass").toHex())
        user.addToPermissions("inventory:*")
        user.save()
    }


}
def destroy = {
}

}

My ShiroSecurityFilters looks like

class ShiroSecurityFilters {
def filters = {
    all(uri: "/**") {
        before = {
            // Ignore direct views (e.g. the default main index page).
            if (!controllerName) return true

            // Access control by convention.
            accessControl()

        }
    }
}

}

I wanted to give to "Guest" access to inventory scaffold only. However in my application once the user "Guest" logged in its able to access other controllers butI don't want that to happen. I appreciate your help.

If there is an better of using Shiro role, access control and/or permissions, please let me know about it.

Thank you

1

1 Answers

3
votes

OK. let's see...

there is a typo right at the start:

"Admin".isEmpty()

will always be false... and I guess you have no role "false" defined...

And you are looking for "Admin" but create "Administrator"...

Do a

adminRole.save(flush:true, failOnError:true)

instead of adminRole.save(). This will make sure that the object is really saved.

The role Administrator already has all permissions ("*:*") and "admin" is not a typical shiro permission, so you can drop this line... (adminRole.addToPermissions("admin"))

If you do a

user.addToRoles(adminRole)

you don't need to add the "*:*"permission. The role is already enough.

I've now created a test project, installed shiro, did a create-auth-controller, a create-wildcard-realm and a create-filters ShiroSecurity.

Activate logging for BootStrap and Shiro-Realm by adding following two lines to the log4j config in Config.groovy:

debug   'grails.app.conf.BootStrap'
debug   'grails.app.realm'

Here is my BootStrap.groovy: (the interesting part)

def init = { servletContext ->
    def adminRole

    if(ShiroRole.findByName("Administrator")==null){
        adminRole = new ShiroRole(name: "Administrator")
        adminRole.addToPermissions("*:*")
        adminRole.save(flush:true, failOnError:true)
        log.debug adminRole.dump()
    }
    println ShiroUser.findAllByUsername("user").dump()
    log.debug "="*80
    if (ShiroUser.findAllByUsername("user").isEmpty()) {
        def user = new ShiroUser(username: "user", passwordHash: new Sha256Hash("pass").toHex())
        user.addToRoles(adminRole)
        user.save(flush:true, failOnError:true)
        log.debug user.dump()
    }

    if (ShiroUser.findAllByUsername("Guest").isEmpty()) {
        def user = new ShiroUser(username: "Guest", passwordHash: new Sha256Hash("pass").toHex())
        user.addToPermissions("inventory:*")
        user.save(flush:true, failOnError:true)
        log.debug user.dump()
    }

}

and my ShiroSecurityFilters.groovy:

def filters = {
    all(controller:'*', action:'*') {
        before = {
        // Ignore direct views (e.g. the default main index page).
        if (!controllerName) return true

        // Access control by convention.
        accessControl()

        }
    }
}

and it works...

As you can see, my SecurityFilters are based on controller and action... just my preference...

But I guess your problem was only based on the wrong bootstrap. Logging is very useful when you work with shiro...