Last updated by azirbes 4 years ago
LDAP configuration is beyond the scope of this document as there are many possible ways to configure an LDAP repository. I'll assume that you have the following server configuration:
NameValue
directory basedc=example,dc=com
repository admin DNcn=admin,dc=example,dc=com
repository admin passwordsecret
server addressldapserver
server port389

Summary of steps:

  1. create a Grails application
  2. install and configure the Spring Security plugin
  3. configure LDAP parameters
  4. populate LDAP with groups and users
  5. create secure page for testing
  6. start the server
  7. create security mapping for secure page
  8. create user in the database corresponding to an LDAP user
  9. test
These steps are very similar to the ones in the basic tutorial - check out that page for more details.

Create your Grails application

# grails create-app bookstore
# cd bookstore

Install the Spring Security plugin

# grails install-plugin acegi

Create the User, Role, and Requestmap domain classes

# grails create-auth-domains User Role Requestmap
Edit User.groovy and change the passwd constraint from 'passwd(blank: false)' to 'passwd(nullable: true)' since passwords are stored in LDAP

Optional - create controllers and GSPs for User, Role, and Requestmap domain classes

# grails generate-manager

Optional - create controllers and GSPs for Captcha, Register, and an Emailer Service

# grails generate-registration

Create a controller that will be restricted by role

# grails create-controller Secure
This will create grails-app/controllers/SecureController.groovy - add some output so we can verify that things are working:
class SecureController {

def index = { render 'Secure access only' } }

Configure Parameters

Security parameters are kept in grails-app/conf/SecurityConfig.groovy; the default values and the new values are summarized in this table:

NameDefaultNew Value
useLdapfalsetrue
ldapSearchSubtreetrueunchanged
ldapGroupRoleAttribute'cn'unchanged
ldapServernull'ldap://ldapserver:389'
ldapManagerDnnull'cn=admin,dc=example,dc=com'
ldapManagerPasswordnull'secret'
ldapSearchBasenull'dc=example,dc=com'
ldapSearchFilternull'(uid={0})'
ldapGroupSearchBasenull'ou=groups,dc=example,dc=com'
ldapGroupSearchFilternull'uniquemember={0}'
ldapRetrieveGroupRolestruefalse if you don't want to convert LDAP groups to Roles
ldapRetrieveDatabaseRolesfalsetrue if you want to access Roles from your database

so the corresponding config file entries would look like:

security {

active = true … useLdap = true ldapRetrieveDatabaseRoles = false ldapRetrieveGroupRoles = true ldapServer = 'ldap://ldapserver:389' ldapManagerDn = 'cn=admin,dc=example,dc=com' ldapManagerPassword = 'secret' ldapSearchBase = 'dc=example,dc=com' ldapSearchFilter = '(uid={0})' ldapGroupSearchBase = 'ou=groups,dc=example,dc=com' ldapGroupSearchFilter = 'uniquemember={0}' }

Populate LDAP with groups and users

If you don't have LDAP users and groups already, configure an LDAP server and use these entries for testing:

dn: dc=example,dc=com
objectClass: dcObject
objectClass: organizationalUnit
dc: example
ou: Example Dot Com

dn: ou=groups,dc=example,dc=com objectclass: organizationalUnit ou: groups

dn: cn=USER,ou=groups,dc=example,dc=com objectclass: groupOfUniqueNames cn: USER uniqueMember: cn=Some Person,ou=company_name,dc=example,dc=com uniqueMember: cn=Some Person2,ou=company_name,dc=example,dc=com uniqueMember: cn=Some Person3,ou=company_name,dc=example,dc=com

dn: cn=ADMIN,ou=groups,dc=example,dc=com objectclass: groupOfUniqueNames cn: ADMIN uniqueMember: cn=Some Person2,ou=company_name,dc=example,dc=com

dn: ou=company_name,dc=example,dc=com objectclass: organizationalUnit ou: company_name description: the name of the company

dn: cn=Some Person,ou=company_name,dc=example,dc=com objectclass: person objectclass: organizationalPerson objectclass: inetOrgPerson uid: some.person userPassword: {SHA}44rSFJQ9qtHWTBAvrsKd5K/p2j0= cn: Some Person sn: Person description: USER

dn: cn=Some Person2,ou=company_name,dc=example,dc=com objectclass: person objectclass: organizationalPerson objectclass: inetOrgPerson uid: some.person2 userPassword: {SHA}KqYKj/f81HPTIeAUav2eJt85UUc= cn: Some Person2 sn: Person2 description: USER description: ADMIN

dn: cn=Some Person3,ou=company_name,dc=example,dc=com objectclass: person objectclass: organizationalPerson objectclass: inetOrgPerson uid: some.person3 userPassword: {SHA}ERnP037iRzV+A0oI2ETuol9v0g8= cn: Some Person3 sn: Person3 description: USER

This will create the following users:
usernamepasswordroles
some.person1password1ROLE_USER
some.person2password2ROLE_USER, ROLE_ADMIN
some.person3password3ROLE_USER

Start the server

# grails run-app
Navigate to http://localhost:8080/bookstore/requestmap/create and create the mapping for SecureController:

and navigate to http://localhost:8080/bookstore/user/create (or http://localhost:8080/bookstore/register) to create a test user (leave the password blank or remove the entire field from the GSP since they're stored in LDAP): Now navigate to http://localhost:8080/bookstore/secure and you should be presented with the login page:

Log in with the username you used for the test user and the password that's stored in LDAP, and you should again be able to see the secure page:

If you prefer to store your url/role mapping statically instead of in the database, skip the Requestmap step and instead make these changes in grails-app/conf/SecurityConfig.groovy:

  • change the 'useRequestMapDomainClass' property to false
  • uncomment the 'requestMapString' property and change its value to:
requestMapString = '''
   CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
   PATTERN_TYPE_APACHE_ANT

/secure/**=ROLE_ADMIN /**=IS_AUTHENTICATED_ANONYMOUSLY '''

Notes

  • By default LDAP group memberships will be converted to Spring Security roles. For example, if a user belongs to the 'Administrator' and 'Manager' groups, these will be converted to ROLE_ADMINISTRATOR and ROLE_MANAGER Roles. You can disable this lookup by setting the 'ldapRetrieveGroupRoles' attribute to false. In this case you'd want to store Roles in your database and access them via your Role domain class and GORM - set the 'ldapRetrieveDatabaseRoles' attribute to true and configure Users' roles just as you would for a regular database-backed authentication store. If both attributes are true, both stores will be searched for Roles.
  • Spring LDAP assumes that passwords are SHA-encoded
  • It may seem redundant to have a User class in the database and also store user-data in LDAP, but this allows more flexibility since you'd want to store application-specific information in the database but shared data in LDAP