Announcement Announcement Module
Collapse
No announcement yet.
Configuring Spring Security Core Plugin Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Configuring Spring Security Core Plugin

    I'd like to secure my grails application with the spring-security-core and spring-security-cas plugins. However, I'm unsure how to map my db tables to the 3 required domain classes. Can anyone suggest how I should configure the 3 domain classes?

    My db table -- "users" -- has 3 pertinent fields: "username", "password", and "authorities".

    The "authorities" field is a string containing all the users roles -- i.e.
    ROLE_ADMIN,ROLE_USER
    My db doesn't have a table that matches the "Authority" domain class.

  • #2
    The plugin expects that there will be 4 booleans in the User class that control whether the user is enabled, locked, etc. If you don't need these, you can add transient fields with hard-coded values. You don't need a Role class or table - just a way to get the roles that are associated with each user.

    So given a User class like this:

    Code:
    package com.yourcompany.yourapp
    
    class User {
       String username
       String password
       String authorities
    }
    you can make these changes:

    Code:
    package com.yourcompany.yourapp
    
    import org.springframework.security.core.authority.GrantedAuthorityImpl
    
    class User {
    
       String username
       String password
       String authorities
    
       boolean enabled = true
       boolean accountExpired = false
       boolean accountLocked = false
       boolean passwordExpired = false
    
       static transients = ['enabled', 'accountExpired', 'accountLocked', 'passwordExpired', 'roles']
    
       static constraints = {
          username blank: false, unique: true
          password blank: false
       }
    
       Set<GrantedAuthorityImpl> getRoles() {
          (authorities ?: '').split(',').collect { new GrantedAuthorityImpl(it.trim()) }
       }
    }
    and you're almost there. Then you need to add two lines to grails-app/conf/Config.groovy:

    Code:
    grails.plugins.springsecurity.userLookup.userDomainClassName = 'com.yourcompany.yourapp.User'
    grails.plugins.springsecurity.userLookup.authoritiesPropertyName = 'roles'

    Comment


    • #3
      Originally posted by burtbeckwith View Post
      The plugin expects that there will be 4 booleans in the User class that control whether the user is enabled, locked, etc.
      Thanks for the explanation; from it I was able to configure spring-security-core (with custom UserDetails & UserDetailsService) and spring-security-cas.

      I had previously reviewed the docs for spring-security-core and I was under the impression: "At a minimum you need a 'person' and an 'authority' domain class." In any event, I was pleasantly surprised at how flexible and easy spring-security-* is to use. Thanks.

      Comment


      • #4
        This post has me 95% of the way to implement the plugin in my application. I'm trying to integrate this with JBOSS Portal that's already using CAS SSO and there is a similar mapping between user's and roles but I can never seem to determine the roles associated with the user.

        JBP_USER table
        JBP_UID
        JBP_UNAME
        JBP_ENABLED

        My User Class
        class SecUser {

        String username
        String password
        boolean enabled
        boolean accountExpired = false
        boolean accountLocked = false
        boolean passwordExpired = false

        static transients = ['accountExpired', 'accountLocked', 'passwordExpired']//, 'roles']

        static constraints = {
        username blank: false, unique: true
        password blank: false
        }

        static mapping = {
        table 'UDBADMIN.JBP_USERS'
        cache usage:'read-write', include:'non-lazy'
        version false

        columns {
        id column:'JBP_UID'
        enabled column:'JBP_ENABLED'
        username column:'JBP_UNAME'
        //firstName column:'JBP_GIVENNAME'
        //lastName column:'JBP_FAMILYNAME'
        password column:'JBP_PASSWORD'
        }


        }

        //static mapping = {
        // password column: '`password`'
        //}

        Set<SecRole> getAuthorities() {
        SecUserSecRole.findAllBySecUser(this).collect { it.secRole } as Set
        }
        }

        JBP_ROLES table
        JBP_RID
        JBP_NAME

        My Role Class

        class SecRole {

        String authority

        /*static mapping = {
        cache true
        }*/

        static mapping = {
        table 'UDBADMIN.JBP_ROLES'
        cache usage:'read-write', include:'non-lazy'
        version false

        columns{
        id column:'JBP_RID'
        authority column:'JBP_NAME'
        //roleDisplayName column:'JBP_DISPLAYNAME'
        }

        }

        static constraints = {
        authority blank: false, unique: true
        }
        }


        JBP_ROLE_MEMEBERSHIP table
        JBP_UID
        JBP_RID


        My Mapping Class

        import org.apache.commons.lang.builder.HashCodeBuilder

        class SecUserSecRole implements Serializable {

        SecUser secUser
        SecRole secRole



        boolean equals(other) {
        if (!(other instanceof SecUserSecRole)) {
        return false
        }

        other.secUser?.id == secUser?.id &&
        other.secRole?.id == secRole?.id
        }

        int hashCode() {
        def builder = new HashCodeBuilder()
        if (secUser) builder.append(secUser.id)
        if (secRole) builder.append(secRole.id)
        builder.toHashCode()
        }

        static SecUserSecRole get(long secUserId, long secRoleId) {

        find 'from SecUserSecRole where secUser.id=:secUserId and secRole.id=:secRoleId',
        [secUserId: secUserId, secRoleId: secRoleId]
        }

        static SecUserSecRole create(SecUser secUser, SecRole secRole, boolean flush = false) {
        new SecUserSecRole(secUser: secUser, secRole: secRole).save(flush: flush, insert: true)
        }

        static boolean remove(SecUser secUser, SecRole secRole, boolean flush = false) {
        SecUserSecRole instance = SecUserSecRole.findBySecUserAndSecRole(secUser, secRole)
        instance ? instance.delete(flush: flush) : false
        }

        static void removeAll(SecUser secUser) {
        executeUpdate 'DELETE FROM SecUserSecRole WHERE secUser=:secUser', [secUser: secUser]
        }

        static void removeAll(SecRole secRole) {
        executeUpdate 'DELETE FROM SecUserSecRole WHERE secRole=:secRole', [secRole: secRole]
        }

        static mapping = {
        table 'UDBADMIN.JBP_ROLE_MEMBERSHIP'
        cache usage:'read-write', include:'non-lazy'
        secRole column:'JBP_RID'
        secUser column:'JBP_UID'

        id composite: ['secUser', 'secRole']

        version false
        }
        }


        Config.groovy

        // Added by the Spring Security Core plugin:
        grails.plugins.springsecurity.userLookup.userDomai nClassName = 'com.lst.SecUser'
        grails.plugins.springsecurity.userLookup.authority JoinClassName = 'com.lst.SecUserSecRole'
        grails.plugins.springsecurity.authority.className = 'com.lst.SecRole'

        Thanks

        Comment


        • #5
          Turns out this is correctly mapping the user with the roles. I added a println to see the roles associated with the user.

          SecUser
          Set<SecRole> getAuthorities() {
          SecUserSecRole.findAllBySecUser(this).collect{
          println(it.secRole.authority)
          it.secRole
          } as Set
          }

          Output
          Admin
          Design
          ITUser

          I added a simple class called TestPost and added @Secured to the controler as such:

          TestPostController

          import grails.plugins.springsecurity.Secured;

          class TestPostController {

          static allowedMethods = [save: "POST", update: "POST", delete: "POST"]


          @Secured(['IS_AUTHENTICATED_FULLY'])
          def index = {
          redirect(action: "list", params: params)
          }

          @Secured(['ROLE_Admin','ROLE_ITUser'])
          def list = {
          params.max = Math.min(params.max ? params.int('max') : 10, 100)
          [testPostInstanceList: TestPost.list(params), testPostInstanceTotal: TestPost.count()]
          }

          However, the LoginControler is returning:
          "LoginControler:denied"

          http://localhost:8080/Test/login/denied
          "Sorry, you're not authorized to view this page."

          Thanks

          Comment


          • #6
            Sorry, you're not authorized to view this page.

            Hi,

            my first atempt to get spring security to work was pretty fine.
            Then I've decided to add a Custom UserDetailsService.
            I manage to login but nothing else.
            Regardless the fact theuser has proper permission it always get "Sorry, you're not authorized to view this page."

            My user class returns

            Collection<Role> getAuthorities() {
            UserRole.findAllByUser(this).collect { it.role }
            }


            Also

            class IntranetUser extends User{

            transient springSecurityService

            String firstName
            String lastName
            String email
            long id

            public IntranetUser(String username, String password, boolean enabled, boolean accountNonExpired, boolean credentialsNonExpired,
            boolean accountNonLocked, Collection<? extends GrantedAuthority> authorities, long userid, String fName, String lName, String mail) {
            super(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, authorities);
            firstName = fName
            lastName = lName
            email = mail
            id = userid
            }

            }

            Also the loadUserByUsername method is like it

            UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

            User.withTransaction { status ->

            User user = User.findByUsername(username)
            if (!user) throw new UsernameNotFoundException(
            'User not found', username)

            def authorities = user.authorities.collect {
            new GrantedAuthorityImpl(it.authority)
            }

            //IntranetUser(String username, String password, boolean enabled,
            // boolean accountNonExpired, boolean credentialsNonExpired,
            //boolean accountNonLocked, Collection<? extends GrantedAuthority> authorities,
            //String firstName, String lastName) {
            return new IntranetUser(user.username, user.password, user.enabled,
            !user.accountExpired, !user.passwordExpired,
            !user.accountLocked, authorities ?: NO_ROLES, user.id,
            user.firstName, user.lastName, user.email)
            }
            }
            }



            Groovy.config looks like

            // Added by the Spring Security Core plugin:
            grails.plugins.springsecurity.userLookup.userDomai nClassName = 'br.com.fisgo.security.User'
            grails.plugins.springsecurity.userLookup.authority JoinClassName = 'br.com.fisgo.security.UserRole'
            grails.plugins.springsecurity.authority.className = 'br.com.fisgo.security.Role'
            grails.plugins.springsecurity.requestMap.className = 'br.com.fisgo.security.RequestMap'

            grails.plugins.springsecurity.securityConfigType = SecurityConfigType.Requestmap


            Any though?

            Regards,

            Comment


            • #7
              Please start new threads instead of replying to old ones and changing the subject.

              Your setup looks good to me. Are you double-encoding the password? As of 1.2 the User domain class encodes the password, so don't set an encrypted password in the User domain class. If that's not it set the log level for "org.springframework.security" to debug.

              Comment


              • #8
                ok,
                I'll start a new thread next time. I though I was with the same issue

                The authentication is ok, only the authorization is the one failling.
                I believe it's because of request map

                I'm trying to build automatically 2 type of role for each Domain Class: one that is read only and another with full permission.
                ROLE_SINONIMO_CRUD /sinonimo/*
                ROLE_SINONIMO_VIEW /sinonimo/index
                ROLE_SINONIMO_VIEW /sinonimo/show


                The user with full permission ROLE_SINONIMO_CRUD is working fine, the user with read only access is getting the
                "Sorry, you're not authorized to view this page." message

                Is there a required order?



                Originally posted by burtbeckwith View Post
                Please start new threads instead of replying to old ones and changing the subject.

                Your setup looks good to me. Are you double-encoding the password? As of 1.2 the User domain class encodes the password, so don't set an encrypted password in the User domain class. If that's not it set the log level for "org.springframework.security" to debug.

                Comment

                Working...
                X