Posts Tagged ‘grails’

Spring Beans from the Grails console

Posted in Code on May 8th, 2012 by ataylor284 – Comments Off on Spring Beans from the Grails console

For Spring newbies, the objects Spring automatically instantiates and injects can be quite opaque. The grails console is great tool for understanding all the underlying Spring infrastructure.

This little snippet will list all the objects currently managed by Spring:

ctx.getBeanNamesForType(Object).sort().join('\n')

To access a bean by name:

ctx.getBean('beanName')

Or to get a list of services, taking advantage of the grails naming convention:

serviceNames = ctx.getBeanNamesForType(Object).findAll{it.endsWith('Service')}.sort().join('\n')

One of the more useful objects Spring can provide is the dataSource. You can use this for doing ad-hoc SQL manipulation without going through the Hibernate layer.

import groovy.sql.Sql
def dataSource = ctx.getBean('dataSource')
new Sql(dataSource).eachRow('select * from table') { row ->
    println row
}

Encrypting a Database Column in Grails

Posted in Code on December 14th, 2011 by ataylor284 – Comments Off on Encrypting a Database Column in Grails

Grails and hibernate user types make it easy to encrypt tables on a column by column basis.

Note that this approach has some limitations. Most importantly, you won’t be able to make queries based on the encrypted field, since they’ll try to match against the encrypted text instead of the plaintext.

The grails mapping DSL allows the user type to be specified easily:

    import ca.redtoad.crypto.hibernate.EncryptedString

    ...
        static mapping = {
            ccNumber type: EncryptedString
        }

Here’s the implementation of the user type. It stores the encrypted value as a JSON map containing the base64 encoded encrypted value and the salt. A text-based JSON representation is purely for convenience — it could easily be stored in binary form in a BLOB column to save space and parsing overhead.

package ca.redtoad.crypto.hibernate

import java.sql.*
import org.codehaus.groovy.grails.commons.ApplicationHolder
import org.hibernate.*
import org.hibernate.usertype.UserType
import grails.converters.JSON
import java.security.MessageDigest
import javax.crypto.*
import javax.crypto.spec.*

class EncryptedString implements UserType {

    int[] sqlTypes() { [Types.VARCHAR] as int[] }
    Class returnedClass() { String }
    boolean equals(x, y) { x == y }
    int hashCode(x) { x.hashCode() }
    Object deepCopy(value) { value }
    boolean isMutable() { false }
    Serializable disassemble(value) { value }
    def assemble(Serializable cached, owner) { cached }
    def replace(original, target, owner) { original }

    Object nullSafeGet(ResultSet resultSet, String[] names, Object owner) throws HibernateException, SQLException {
        String str = resultSet.getString(names[0])
        str ? decrypt(str) : null
    }

    void nullSafeSet(PreparedStatement statement, Object value, int index) {
        statement.setString(index, value ? encrypt(value) : null)
    }
    private String encrypt(String plaintext) {
        String salt = 'Salt!'
        String key = "myKey"
        Cipher c = Cipher.getInstance('AES')
        byte[] keyBytes = MessageDigest.getInstance('SHA-1').digest("$salt$key".getBytes())[0..<16]
        c.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(keyBytes, 'AES'))
        [data: c.doFinal(plaintext.bytes).encodeBase64() as String, salt: salt] as JSON
    }

    private String decrypt(String ciphertext) {
        def json = JSON.parse(ciphertext)
        Cipher c = Cipher.getInstance('AES')
        String key = "myKey"
        byte[] keyBytes = MessageDigest.getInstance('SHA-1').digest("${json.salt}${key}".getBytes())[0..<16]
        c.init(Cipher.DECRYPT_MODE, new SecretKeySpec(keyBytes, 'AES'))
        new String(c.doFinal(json['data'].decodeBase64()))
    }
}

The H2 Database Console in Grails 2

Posted in Code on November 15th, 2011 by ataylor284 – 1 Comment

The H2 Database Engine replaces HSQLDB as the default, embedded database engine in Grails 2.0. One of the great features it adds is a web-based console for browsing tables, checking the schema, executing SQL queries, and all the other stuff you’d use a database client for.

This was possible in older versions of grails but it comes ready to go out of the box in Grails 2. It’s mapped to http://localhost:8080/<app-name>/dbconsole.

Let’s create a quick grails app to see it in action:

$ grails create-app test-app
| Created Eclipse project files.
| Created Grails Application at ~/dev/test-app
$ cd test-app
$ grails
| Enter a script name to run. Use TAB for completion:
grails> run-app
| Server running. Browse to http://localhost:8080/test-app
| Application loaded in interactive mode. Type 'exit' to shutdown.
| Enter a script name to run. Use TAB for completion:
grails>

At this point, browse to http://localhost:8080/test-app/dbconsole. The default login parameters should match the defaults in grails-app/conf/DataSource.groovy, so pressing Connect should log us into the development database.

H2 Database Console Login Window

H2 Database Console Login Window

grails> create-domain-class test.Book
| Created file grails-app/domain/test/Book.groovy

Book.groovy will be an empty domain class, so open it up add a title property. Then hit refresh in the console, and now we see a BOOK table in the right sidebar. Let’s create a book instance with the grails shell:

grails> shell
| Packaging Grails application.....
Groovy Shell (1.8.3, JVM: 1.6.0_29)
Type 'help' or '\h' for help.
-------------------------------------------------------------------------------
groovy:000> new test.Book(title: 'Grails in Action').save(failOnError: true)
===> test.Book : 1
groovy:000> exit
grails>

Now if we enter SELECT * FROM BOOK in the database console, our book will show up.

H2 Database Console

H2 Database Console

Grails 2.0 and emacs shell-mode

Posted in Uncategorized on September 16th, 2011 by ataylor284 – Comments Off on Grails 2.0 and emacs shell-mode

I’ve been testing out Grails 2.0.0.M2 a bit and I really like the reduced clutter in the output.

Emacs shell-mode doesn’t handle the new output style well, though. The control characters grails uses to keep the output on one line are not interpreted properly and get echoed to the buffer. Although ansi-term works, shell-mode provides much better integration with emacs.

Here’s a snippet of elisp to fix it:

(defun grails-comint-magic (string)
  "Handle grails output gracefully."
  (let ((position (process-mark (get-buffer-process (current-buffer)))))
    (save-excursion
      (goto-char comint-last-output-start)
      (while (re-search-forward "\033\\[1A\033\\[[0-9]+D\033\\[0K" position t)
        (replace-match "" t t)
        (previous-line)
        (delete-region
         (line-beginning-position)
         (progn (forward-line 1) (point)))))))
(add-hook 'comint-output-filter-functions 'grails-comint-magic)

It simply recognizes the sequence of control characters grails generates and simulates the intent directly with emacs commands.

Throw this in your .emacs and enjoy.

Getting Started with Grails and MySQL

Posted in Code on June 29th, 2011 by ataylor284 – 1 Comment

Out of the box, grails is set up with a HSQLDB database ready to go. While HSQLDB is great for early development, eventually most projects have to migrate to a real database system. If you’re using a hosting service for your app, such as CloudFoundry, it will probably end up being MySQL.

Here’s my checklist of things to do to convert a project from the default HSQLDB settings to MySQL:

  • Add the MySQL driver to your project. There are two ways to do this:
    • Download the jar file and put it in your ${project}/lib directory
    • Or, add a runtime dependency in grails-app/conf/BuildConfig.groovy. There will already be one commented out from the default BuildConfig, but you may want to bump the version number to the most recent. To resolve dependencies this way, you’ll have to make sure you’ve got a repository with the MySQL driver set up; I generally uncomment mavenCentral().
  • create a MySQL database and set the credentials (or get them from your service provider or DBA)
  • change the following in grails-app/conf/DataSource.groovy
    • The username and password of your MySQL database. I usually move these from the global dataSource section into the environment specific part since the prod password will probably be different than the dev and test.
    • The driverClassName. It should be com.mysql.jdbc.Driver.
    • The SQL dialect. MySQL will generally default to the MyISAM engine. InnoDB is a much better choice for the typical app for foreign key constraints and transactions, two features MyISAM lacks. Set it to org.hibernate.dialect.MySQL5InnoDBDialect.
    • Add show_sql=true to the global or development hibernate section if you want hibernate to log all the SQL statements it generates.
    • The JDBC URL. I recommend something like jdbc:mysql://HOSTNAME/DBNAME?useUnicode=yes&characterEncoding=UTF-8 because most MySQL installs will default to the latin-1 charset.

Your new DataSource.groovy should look something like this:

dataSource {
    pooled = true
    driverClassName = "com.mysql.jdbc.Driver"
    dialect = "org.hibernate.dialect.MySQL5InnoDBDialect" 
}
hibernate {
    cache.use_second_level_cache = true
    cache.use_query_cache = true
    cache.provider_class = 'net.sf.ehcache.hibernate.EhCacheProvider'
}
// environment specific settings
environments {
    development {
        dataSource {
            dbCreate = "create" // one of 'create', 'create-drop','update'
            url = "jdbc:mysql://localhost/DEVDBNAME?useUnicode=yes&characterEncoding=UTF-8"
            username = "dev"
            password = "devpw"
        }
        hibernate {
            show_sql = true
        }
    }
    test {
        dataSource {
            dbCreate = "create-drop" // one of 'create', 'create-drop','update'
            url = "jdbc:mysql://localhost/TESTDBNAME?useUnicode=yes&characterEncoding=UTF-8"
            username = "test"
            password = "testpw"
        }
    }
    production {
        dataSource {
            dbCreate = "update"
            url = "jdbc:mysql://localhost/PRODDBNAME?useUnicode=yes&characterEncoding=UTF-8"
            username = "prod"
            password = "prodpw"
        }
    }
}

That’s it. Run your application in dev mode and check to ensure the tables were created in the database.

References:

Logging Spring Security Events in Grails

Posted in Code on May 12th, 2011 by ataylor284 – 1 Comment

The grails spring-security-core plugin is great way to get full featured authentication in a web application with minimal effort. It mostly just works out of the box, and in combination with the spring-security-ui plugin, you can have fully functional login, self-registration (with email confirmation), and administration console with almost no code.

The underlying spring security library uses spring application events to inform the app when interesting stuff happens.

It’s sometimes nice to keep track of when users login — or fail to — and logout. A grails app can hook into spring security events by creating an ApplicationListener class in src/groovy.

Note that spring security doesn’t send events for logouts. Those can be captured by setting up a custom logout handler. Keep in mind you’ll only get logout events if the user logs out directly, rather than the session expiring.

This example handles both regular security events and logouts by logging them.

package ca.redtoad.security

import javax.servlet.http.*
import org.apache.commons.logging.LogFactory
import org.springframework.context.ApplicationListener
import org.springframework.security.authentication.event.AbstractAuthenticationEvent
import org.springframework.security.core.Authentication
import org.springframework.security.web.authentication.logout.LogoutHandler

class LoggingSecurityEventListener implements 
    ApplicationListener<AbstractAuthenticationEvent>, LogoutHandler {

    private static final log = LogFactory.getLog(this)

    void onApplicationEvent(AbstractAuthenticationEvent event) {
        event.authentication.with {
            def username = principal.hasProperty('username')?.getProperty(principal) ?: principal
            log.info "event=${event.class.simpleName} username=${username} " +
                "remoteAddress=${details.remoteAddress} sessionId=${details.sessionId}"
        }
    }

    void logout(HttpServletRequest request, HttpServletResponse response, 
        Authentication authentication) {
        authentication.with {
            def username = principal.hasProperty('username')?.getProperty(principal) ?: principal
            log.info "event=Logout username=${username} " +
                "remoteAddress=${details.remoteAddress} sessionId=${details.sessionId}"
        }
    }
}

Next the security event listener has to be registered as a spring bean in grails-app/conf/spring/resources.groovy.

import ca.redtoad.security.LoggingSecurityEventListener

beans = {
    securityEventListener(LoggingSecurityEventListener)
}

Finally, we need make two additions to grails-app/conf/Config.groovy: turn on the grails security event listener, and override the logout handlers to include ours.

grails.plugins.springsecurity.useSecurityEventListener = true
grails.plugins.springsecurity.logout.handlerNames = 
    ['rememberMeServices',
     'securityContextLogoutHandler', 
     'securityEventListener']

Setting a Functional Test Database in Grails

Posted in Code on February 11th, 2011 by ataylor284 – Comments Off on Setting a Functional Test Database in Grails

So functional testing is unexpectedly easy to get running in grails. Installed the grails geb plugin, and it pretty much works out of the box. The main problem I ran into was that functional tests use the same database as integration tests. My suite of integration tests expect a pristine database and each test selectively populates it with test fixtures. Since integration test transactions get rolled back, the database stays clean.

Functional tests, on the other hand, require a real working application. Ideally, the database would be in fully populated with data representative of what’s deployed in the real world. Also, the database transactions don’t get rolled back like in the integration test phase, so test data accumulates.

Rather than trying to force the two types of tests to play nicely together, I thought it would be smarter to just use two different database instances. Even though the current test phase isn’t easily accessible, grails has a really great way to hook into the build system with events.

Capturing the Test Phase

You can capturing build events by creating a script called scripts/Events.groovy. The event we want is TestPhaseStart. Here’s an example that stuffs the current phase into a system property:

eventTestPhaseStart = { args ->
	System.properties["grails.test.phase"] = args
}

Setting the Database Dynamically

Once the test phase is in a system property, it’s easy to set the database with it. DataSource.groovy is, of course, a groovy script, so any kind of conditional logic is fine. One approach is to just embed the test phase name into the database name:

environments {
    test {
        dataSource {
            def dbName = "project-${System.properties['grails.test.phase']}"
            url = "jdbc:postgresql://localhost:5432/$dbName"
            driverClassName = "org.postgresql.Driver"
            dialect = org.hibernate.dialect.PostgreSQLDialect
            username = "testuser"
            password = "testpassword"
        }
    }
}

With this config, the functional tests will use a database called project-functional, and the integration tests will use a database called project-integration. Problem solved.

For more details on the grails event model, check out Mastering Grails: The Grails event model.

Cross Site Request Forgeries (CSRF) and Grails

Posted in Code on January 26th, 2011 by ataylor284 – 6 Comments

I recently had to come up with defenses against cross-site request forgery (CSRF) attacks for a grails application. This goes along with hand-in-hand with XSS injection protection to make your site as secure as possible. There’s lots of information spread out on the internet about CSRFs, but nothing specifically for grails, so here’s a quick guide I whipped up.

Require POST

Forms that change state should be submitted with POSTs. In views, g:forms should use the post method. This is the default for g:form tags, but regular form tags default to GET, so I prefer to make it explicit.

In controllers, limit the accepted methods for your actions with a static allowedMethods block. If the form gets submitted with a get, grails will return a 405 error code to the browser.

class SomethingController {
    static allowedMethods = [save: 'POST', update: 'POST',
        delete: 'POST']

    ...

}

Use A Form Token

Use the one-time token grails provides. This prevents accidental double submits, but it also rejects forged requests that weren’t submitted from your form page. A unique token is generated when the form gets loaded, and if it’s wrong or not present when the form get submitted, the controller can return an error.

<g:form action="save" method="post" useToken="true">

Wrap your controller in a withForm block:

class SomethingController {
    ...

    def save = {
        withForm {
            // token was correct, save the object
        }.invalidToken {
            response.status = 405
        }
    }
}

Verify the referer

The referer HTTP header will be set to form that submitted your request. This should be from your application, and it’s easy to test it and ensure it really is. No need for this on GET requests though, since it’ll break bookmarks and deep links in. This can be enforced on POSTs with a simple filter in grails-app/conf:

import org.codehaus.groovy.grails.commons.ConfigurationHolder as CH

class RefererFilters {
    // referer must match serverURL, optionally https
    static validRefererPrefix = "^${CH.config.grails.serverURL}".replace("http", "https?")
    def filters = {
        checkReferer(controller: '*', action: '*') {
            before = {
                if (request.method.toUpperCase() == "POST") {
                    def referer = request.getHeader('Referer')

                    return referer && referer =~ validRefererPrefix
                }
            }
        }
    }
}

(Maybe) Adjust the session timeout

The default session duration for tomcat is 30 minutes. A lower value can close the time window for CSRFs, but can also harm the usability of the site. To customize it, run grails install-templates add this to src/templates/war/web.xml inside the web-app tag:

<session-config>
   <session-timeout>60</session-timeout>
</session-config>

References: