Results 1 to 8 of 8

Thread: Configuring Spring Security Core Plugin

  1. #1

    Question 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. #2
    Join Date
    Jul 2007
    Posts
    123

    Default

    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'

  3. #3

    Default

    Quote 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.

  4. #4
    Join Date
    Sep 2010
    Posts
    6

    Post

    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

  5. #5
    Join Date
    Sep 2010
    Posts
    6

    Default

    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

  6. #6

    Default 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,

  7. #7
    Join Date
    Jul 2007
    Posts
    123

    Default

    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.

  8. #8

    Default

    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?



    Quote 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.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •